about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/tools/rust-analyzer/.github/workflows/ci.yaml4
-rw-r--r--src/tools/rust-analyzer/.github/workflows/publish-libs.yaml1
-rw-r--r--src/tools/rust-analyzer/.github/workflows/release.yaml17
-rw-r--r--src/tools/rust-analyzer/Cargo.lock43
-rw-r--r--src/tools/rust-analyzer/Cargo.toml11
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/input.rs84
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/lib.rs6
-rw-r--r--src/tools/rust-analyzer/crates/flycheck/src/lib.rs8
-rw-r--r--src/tools/rust-analyzer/crates/flycheck/src/test_runner.rs5
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/attr.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/data.rs9
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/generics.rs80
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lib.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs85
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs42
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/proc_macro.rs14
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/resolver.rs20
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs165
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/db.rs65
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs38
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/lib.rs21
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs42
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/Cargo.toml3
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/builder.rs34
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs13
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs14
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs27
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/db.rs16
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs17
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs84
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs82
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer.rs159
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs17
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs39
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs9
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs28
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lib.rs95
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower.rs239
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs15
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs56
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs65
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs15
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/regression.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs109
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/utils.rs166
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/display.rs33
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs60
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/item.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render.rs49
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/predicate.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs47
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/lib.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs27
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mutability_errors.rs50
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_trailing_return.rs19
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs23
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs7
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs28
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs32
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/doc_links.rs16
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs30
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/file_structure.rs13
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs71
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/render.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/tests.rs175
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs96
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs9
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_captures.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/fn_lifetime_fn.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/range_exclusive.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/lib.rs28
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/static_index.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/status.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs48
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/html.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tags.rs9
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html7
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html8
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html83
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html9
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html15
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html57
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_outline.html1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_operators.html1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html5
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html11
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs76
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/test_explorer.rs68
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/typing.rs33
-rw-r--r--src/tools/rust-analyzer/crates/load-cargo/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/load-cargo/src/lib.rs4
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/benchmark.rs20
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/expander.rs45
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs160
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs99
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/lib.rs64
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/parser.rs100
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs56
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/to_parser_input.rs6
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/tt_iter.rs14
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs58
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0034_match_arms_recovery.rast113
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0034_match_arms_recovery.rs11
-rw-r--r--src/tools/rust-analyzer/crates/paths/Cargo.toml6
-rw-r--r--src/tools/rust-analyzer/crates/paths/src/lib.rs242
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs5
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs12
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs2
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs4
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs47
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs26
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/proc_macros.rs2
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/server/token_stream.rs4
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs16
-rw-r--r--src/tools/rust-analyzer/crates/project-model/Cargo.toml3
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs19
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs21
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/lib.rs4
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/project_json.rs20
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/sysroot.rs6
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/tests.rs20
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/workspace.rs86
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml3
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs5
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs1
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs12
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs49
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs5
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs18
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs31
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs6
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs4
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/semantic_tokens.rs3
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs107
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs36
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs92
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/tests/crate_graph.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs13
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs6
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/testdir.rs22
-rw-r--r--src/tools/rust-analyzer/crates/span/src/lib.rs50
-rw-r--r--src/tools/rust-analyzer/crates/syntax/Cargo.toml4
-rw-r--r--src/tools/rust-analyzer/crates/syntax/rust.ungram2
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs3378
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/generated/tokens.rs80
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/tests.rs25
-rw-r--r--src/tools/rust-analyzer/crates/test-fixture/src/lib.rs25
-rw-r--r--src/tools/rust-analyzer/crates/toolchain/Cargo.toml3
-rw-r--r--src/tools/rust-analyzer/crates/toolchain/src/lib.rs43
-rw-r--r--src/tools/rust-analyzer/crates/tt/Cargo.toml5
-rw-r--r--src/tools/rust-analyzer/crates/tt/src/lib.rs11
-rw-r--r--src/tools/rust-analyzer/crates/vfs-notify/src/lib.rs6
-rw-r--r--src/tools/rust-analyzer/crates/vfs/src/lib.rs57
-rw-r--r--src/tools/rust-analyzer/crates/vfs/src/loader.rs2
-rw-r--r--src/tools/rust-analyzer/crates/vfs/src/vfs_path.rs2
-rw-r--r--src/tools/rust-analyzer/docs/dev/lsp-extensions.md14
-rw-r--r--src/tools/rust-analyzer/docs/user/generated_config.adoc5
-rw-r--r--src/tools/rust-analyzer/editors/code/package.json9
-rw-r--r--src/tools/rust-analyzer/editors/code/src/config.ts25
-rw-r--r--src/tools/rust-analyzer/editors/code/src/debug.ts6
-rw-r--r--src/tools/rust-analyzer/editors/code/src/lsp_ext.ts6
-rw-r--r--src/tools/rust-analyzer/editors/code/src/run.ts28
-rw-r--r--src/tools/rust-analyzer/editors/code/src/tasks.ts50
-rw-r--r--src/tools/rust-analyzer/editors/code/src/test_explorer.ts63
-rw-r--r--src/tools/rust-analyzer/xtask/Cargo.toml4
-rw-r--r--src/tools/rust-analyzer/xtask/src/codegen.rs2
-rw-r--r--src/tools/rust-analyzer/xtask/src/codegen/grammar.rs (renamed from src/tools/rust-analyzer/crates/syntax/src/tests/sourcegen_ast.rs)72
-rw-r--r--src/tools/rust-analyzer/xtask/src/codegen/grammar/ast_src.rs (renamed from src/tools/rust-analyzer/crates/syntax/src/tests/ast_src.rs)0
-rw-r--r--src/tools/rust-analyzer/xtask/src/dist.rs21
-rw-r--r--src/tools/rust-analyzer/xtask/src/flags.rs141
-rw-r--r--src/tools/rust-analyzer/xtask/src/install.rs16
223 files changed, 5731 insertions, 3632 deletions
diff --git a/src/tools/rust-analyzer/.github/workflows/ci.yaml b/src/tools/rust-analyzer/.github/workflows/ci.yaml
index 2d8946520d5..08ad10c2971 100644
--- a/src/tools/rust-analyzer/.github/workflows/ci.yaml
+++ b/src/tools/rust-analyzer/.github/workflows/ci.yaml
@@ -71,7 +71,7 @@ jobs:
         run: echo "::add-matcher::.github/rust.json"
 
       - name: Cache Dependencies
-        uses: Swatinem/rust-cache@988c164c3d0e93c4dbab36aaf5bbeb77425b2894
+        uses: Swatinem/rust-cache@640a22190e7a783d4c409684cea558f081f92012
         with:
           key: ${{ env.RUST_CHANNEL }}
 
@@ -140,7 +140,7 @@ jobs:
           rustup target add ${{ env.targets }} ${{ env.targets_ide }}
 
       - name: Cache Dependencies
-        uses: Swatinem/rust-cache@988c164c3d0e93c4dbab36aaf5bbeb77425b2894
+        uses: Swatinem/rust-cache@640a22190e7a783d4c409684cea558f081f92012
 
       - name: Check
         run: |
diff --git a/src/tools/rust-analyzer/.github/workflows/publish-libs.yaml b/src/tools/rust-analyzer/.github/workflows/publish-libs.yaml
index 862373ec1cc..34ca53e2e53 100644
--- a/src/tools/rust-analyzer/.github/workflows/publish-libs.yaml
+++ b/src/tools/rust-analyzer/.github/workflows/publish-libs.yaml
@@ -32,4 +32,5 @@ jobs:
           git config --global user.name "GitHub Action"
           # Remove r-a crates from the workspaces so we don't auto-publish them as well
           sed -i 's/ "crates\/\*"//' ./Cargo.toml
+          sed -i 's/ "xtask\/"//' ./Cargo.toml
           cargo workspaces publish --yes --exact --from-git --no-git-commit --allow-dirty
diff --git a/src/tools/rust-analyzer/.github/workflows/release.yaml b/src/tools/rust-analyzer/.github/workflows/release.yaml
index dc0a6c2d91f..11014338d72 100644
--- a/src/tools/rust-analyzer/.github/workflows/release.yaml
+++ b/src/tools/rust-analyzer/.github/workflows/release.yaml
@@ -36,6 +36,7 @@ jobs:
           - os: ubuntu-20.04
             target: x86_64-unknown-linux-gnu
             code-target: linux-x64
+            container: rockylinux:8
           - os: ubuntu-20.04
             target: aarch64-unknown-linux-gnu
             code-target: linux-arm64
@@ -58,10 +59,18 @@ jobs:
 
     steps:
       - name: Checkout repository
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
         with:
           fetch-depth: ${{ env.FETCH_DEPTH }}
 
+      - name: Install toolchain dependencies
+        if: matrix.container == 'rockylinux:8'
+        shell: bash
+        run: |
+          dnf install -y gcc
+          curl --proto '=https' --tlsv1.2 --retry 10 --retry-connrefused -fsSL "https://sh.rustup.rs" | sh -s -- --profile minimal --default-toolchain none -y
+          echo "${CARGO_HOME:-$HOME/.cargo}/bin" >> $GITHUB_PATH
+
       - name: Install Rust toolchain
         run: |
           rustup update --no-self-update stable
@@ -69,9 +78,9 @@ jobs:
           rustup component add rust-src
 
       - name: Install Node.js
-        uses: actions/setup-node@v3
+        uses: actions/setup-node@v4
         with:
-          node-version: 16
+          node-version: 18
 
       - name: Update apt repositories
         if: matrix.target == 'aarch64-unknown-linux-gnu' || matrix.target == 'arm-unknown-linux-gnueabihf'
@@ -181,7 +190,7 @@ jobs:
       - name: Install Nodejs
         uses: actions/setup-node@v4
         with:
-          node-version: 18
+          node-version: 20
 
       - run: echo "TAG=$(date --iso -u)" >> $GITHUB_ENV
         if: github.ref == 'refs/heads/release'
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index 68ed32391b7..c7cf4479b33 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -594,6 +594,7 @@ dependencies = [
  "rustc-hash",
  "scoped-tls",
  "smallvec",
+ "span",
  "stdx",
  "syntax",
  "test-fixture",
@@ -637,6 +638,7 @@ dependencies = [
  "pulldown-cmark",
  "pulldown-cmark-to-cmark",
  "smallvec",
+ "span",
  "stdx",
  "syntax",
  "test-fixture",
@@ -732,6 +734,7 @@ dependencies = [
  "ide-db",
  "itertools",
  "once_cell",
+ "paths",
  "serde_json",
  "stdx",
  "syntax",
@@ -931,6 +934,7 @@ dependencies = [
  "hir-expand",
  "ide-db",
  "itertools",
+ "paths",
  "proc-macro-api",
  "project-model",
  "span",
@@ -1225,6 +1229,9 @@ checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
 [[package]]
 name = "paths"
 version = "0.0.0"
+dependencies = [
+ "camino",
+]
 
 [[package]]
 name = "percent-encoding"
@@ -1375,6 +1382,7 @@ dependencies = [
  "semver",
  "serde",
  "serde_json",
+ "span",
  "stdx",
  "toolchain",
  "tracing",
@@ -1432,9 +1440,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_abi"
-version = "0.42.0"
+version = "0.44.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2ae52e2d5b08762c9464b541345f519b8719d57b643b73632bade43ecece9dc"
+checksum = "b8709df2a746f055316bc0c62bd30948695a25e734863bf6e1f9755403e010ab"
 dependencies = [
  "bitflags 2.4.2",
  "ra-ap-rustc_index",
@@ -1443,9 +1451,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_index"
-version = "0.42.0"
+version = "0.44.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfd7e10c7853fe79443d46e1d2d8ab09fe99926118e59653fb8b480d5045f126"
+checksum = "9ad68bacffb87dcdbb23a3ce11261375078aaa06b85d348c49f39ffd5510dc20"
 dependencies = [
  "arrayvec",
  "ra-ap-rustc_index_macros",
@@ -1454,9 +1462,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_index_macros"
-version = "0.42.0"
+version = "0.44.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "47f1d1c589be6c9a9e852fadee0e60329c0f862e87442ac2fe5adae30663cc76"
+checksum = "8782aaf3a113837c533dfb1c45df91cd17e1fdd1d2f9a20c2e0d1976025c4f1f"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1466,9 +1474,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_lexer"
-version = "0.42.0"
+version = "0.44.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa852373a757b4c723bbdc96ced7f575cad68a1e266e45fee12bc4c69a482d80"
+checksum = "aab683fc8579d09eb72033bd5dc9ba6d701aa9645b5fed087ef19af71184dff3"
 dependencies = [
  "unicode-properties",
  "unicode-xid",
@@ -1476,9 +1484,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_parse_format"
-version = "0.42.0"
+version = "0.44.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2afe3c49accd95a53ac4d72ae13bafc7d115bdd80c8cd56ab09e6fc68f482210"
+checksum = "0bcf9ff5edbf784b67b8ad5e03a068f1300fcc24062c0d476b3018965135d933"
 dependencies = [
  "ra-ap-rustc_index",
  "ra-ap-rustc_lexer",
@@ -1486,9 +1494,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_pattern_analysis"
-version = "0.42.0"
+version = "0.44.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1253da23515d80c377a3998731e0ec3794997b62b989fd47db73efbde6a0bd7c"
+checksum = "d63d1e1d5b2a13273cee1a10011147418f40e12b70f70578ce1dee0f1cafc334"
 dependencies = [
  "ra-ap-rustc_index",
  "rustc-hash",
@@ -1598,6 +1606,7 @@ dependencies = [
  "oorandom",
  "parking_lot",
  "parser",
+ "paths",
  "proc-macro-api",
  "profile",
  "project-model",
@@ -1869,20 +1878,16 @@ dependencies = [
  "itertools",
  "once_cell",
  "parser",
- "proc-macro2",
- "quote",
  "ra-ap-rustc_lexer",
  "rayon",
  "rowan",
  "rustc-hash",
  "smol_str",
- "sourcegen",
  "stdx",
  "test-utils",
  "text-edit",
  "tracing",
  "triomphe",
- "ungrammar",
 ]
 
 [[package]]
@@ -2024,6 +2029,7 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
 name = "toolchain"
 version = "0.0.0"
 dependencies = [
+ "camino",
  "home",
 ]
 
@@ -2109,7 +2115,6 @@ name = "tt"
 version = "0.0.0"
 dependencies = [
  "smol_str",
- "span",
  "stdx",
  "text-size",
 ]
@@ -2438,8 +2443,12 @@ version = "0.1.0"
 dependencies = [
  "anyhow",
  "flate2",
+ "itertools",
+ "proc-macro2",
+ "quote",
  "stdx",
  "time",
+ "ungrammar",
  "write-json",
  "xflags",
  "xshell",
diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml
index 0679522efd6..d9343d2b963 100644
--- a/src/tools/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/Cargo.toml
@@ -84,11 +84,11 @@ tt = { path = "./crates/tt", version = "0.0.0" }
 vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" }
 vfs = { path = "./crates/vfs", version = "0.0.0" }
 
-ra-ap-rustc_lexer = { version = "0.42.0", default-features = false }
-ra-ap-rustc_parse_format = { version = "0.42.0", default-features = false }
-ra-ap-rustc_index = { version = "0.42.0", default-features = false }
-ra-ap-rustc_abi = { version = "0.42.0", default-features = false }
-ra-ap-rustc_pattern_analysis = { version = "0.42.0", default-features = false }
+ra-ap-rustc_lexer = { version = "0.44.0", default-features = false }
+ra-ap-rustc_parse_format = { version = "0.44.0", default-features = false }
+ra-ap-rustc_index = { version = "0.44.0", default-features = false }
+ra-ap-rustc_abi = { version = "0.44.0", default-features = false }
+ra-ap-rustc_pattern_analysis = { version = "0.44.0", default-features = false }
 
 # local crates that aren't published to crates.io. These should not have versions.
 sourcegen = { path = "./crates/sourcegen" }
@@ -105,6 +105,7 @@ anyhow = "1.0.75"
 arrayvec = "0.7.4"
 bitflags = "2.4.1"
 cargo_metadata = "0.18.1"
+camino = "1.1.6"
 chalk-solve = { version = "0.96.0", default-features = false }
 chalk-ir = "0.96.0"
 chalk-recursive = { version = "0.96.0", default-features = false }
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 b243b37b77b..27eb05cd4dc 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/input.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs
@@ -6,11 +6,12 @@
 //! actual IO. See `vfs` and `project_model` in the `rust-analyzer` crate for how
 //! actual IO is done and lowered to input.
 
-use std::{fmt, mem, ops, str::FromStr};
+use std::{fmt, mem, ops};
 
 use cfg::CfgOptions;
 use la_arena::{Arena, Idx, RawIdx};
 use rustc_hash::{FxHashMap, FxHashSet};
+use span::Edition;
 use syntax::SmolStr;
 use triomphe::Arc;
 use vfs::{file_set::FileSet, AbsPathBuf, AnchoredPath, FileId, VfsPath};
@@ -293,42 +294,11 @@ pub struct CrateData {
     pub is_proc_macro: bool,
 }
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub enum Edition {
-    Edition2015,
-    Edition2018,
-    Edition2021,
-    Edition2024,
-}
-
-impl Edition {
-    pub const CURRENT: Edition = Edition::Edition2021;
-    pub const DEFAULT: Edition = Edition::Edition2015;
-}
-
 #[derive(Default, Debug, Clone, PartialEq, Eq)]
 pub struct Env {
     entries: FxHashMap<String, String>,
 }
 
-impl Env {
-    pub fn new_for_test_fixture() -> Self {
-        Env {
-            entries: FxHashMap::from_iter([(
-                String::from("__ra_is_test_fixture"),
-                String::from("__ra_is_test_fixture"),
-            )]),
-        }
-    }
-}
-
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub enum DependencyKind {
-    Normal,
-    Dev,
-    Build,
-}
-
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Dependency {
     pub crate_id: CrateId,
@@ -530,13 +500,6 @@ impl CrateGraph {
         }
     }
 
-    // FIXME: this only finds one crate with the given root; we could have multiple
-    pub fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> {
-        let (crate_id, _) =
-            self.arena.iter().find(|(_crate_id, data)| data.root_file_id == file_id)?;
-        Some(crate_id)
-    }
-
     pub fn sort_deps(&mut self) {
         self.arena
             .iter_mut()
@@ -653,6 +616,10 @@ impl CrateGraph {
         }
         id_map
     }
+
+    pub fn shrink_to_fit(&mut self) {
+        self.arena.shrink_to_fit();
+    }
 }
 
 impl ops::Index<CrateId> for CrateGraph {
@@ -670,32 +637,6 @@ impl CrateData {
     }
 }
 
-impl FromStr for Edition {
-    type Err = ParseEditionError;
-
-    fn from_str(s: &str) -> Result<Self, Self::Err> {
-        let res = match s {
-            "2015" => Edition::Edition2015,
-            "2018" => Edition::Edition2018,
-            "2021" => Edition::Edition2021,
-            "2024" => Edition::Edition2024,
-            _ => return Err(ParseEditionError { invalid_input: s.to_owned() }),
-        };
-        Ok(res)
-    }
-}
-
-impl fmt::Display for Edition {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.write_str(match self {
-            Edition::Edition2015 => "2015",
-            Edition::Edition2018 => "2018",
-            Edition::Edition2021 => "2021",
-            Edition::Edition2024 => "2024",
-        })
-    }
-}
-
 impl Extend<(String, String)> for Env {
     fn extend<T: IntoIterator<Item = (String, String)>>(&mut self, iter: T) {
         self.entries.extend(iter);
@@ -723,19 +664,6 @@ impl Env {
 }
 
 #[derive(Debug)]
-pub struct ParseEditionError {
-    invalid_input: String,
-}
-
-impl fmt::Display for ParseEditionError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "invalid edition: {:?}", self.invalid_input)
-    }
-}
-
-impl std::error::Error for ParseEditionError {}
-
-#[derive(Debug)]
 pub struct CyclicDependenciesError {
     path: Vec<(CrateId, Option<CrateDisplayName>)>,
 }
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 5dcb580723f..785ff9ceffa 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs
@@ -14,9 +14,9 @@ use triomphe::Arc;
 pub use crate::{
     change::FileChange,
     input::{
-        CrateData, CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency,
-        DependencyKind, Edition, Env, LangCrateOrigin, ProcMacroPaths, ReleaseChannel, SourceRoot,
-        SourceRootId, TargetLayoutLoadResult,
+        CrateData, CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Env,
+        LangCrateOrigin, ProcMacroPaths, ReleaseChannel, SourceRoot, SourceRootId,
+        TargetLayoutLoadResult,
     },
 };
 pub use salsa::{self, Cancelled};
diff --git a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
index f8efb520222..4ee86954acd 100644
--- a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
@@ -8,10 +8,10 @@
 
 #![warn(rust_2018_idioms, unused_lifetimes)]
 
-use std::{fmt, io, path::PathBuf, process::Command, time::Duration};
+use std::{fmt, io, process::Command, time::Duration};
 
 use crossbeam_channel::{never, select, unbounded, Receiver, Sender};
-use paths::{AbsPath, AbsPathBuf};
+use paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
 use rustc_hash::FxHashMap;
 use serde::Deserialize;
 
@@ -53,7 +53,7 @@ pub enum FlycheckConfig {
         extra_args: Vec<String>,
         extra_env: FxHashMap<String, String>,
         ansi_color_output: bool,
-        target_dir: Option<PathBuf>,
+        target_dir: Option<Utf8PathBuf>,
     },
     CustomCommand {
         command: String,
@@ -363,7 +363,7 @@ impl FlycheckActor {
                 });
 
                 cmd.arg("--manifest-path");
-                cmd.arg(self.root.join("Cargo.toml").as_os_str());
+                cmd.arg(self.root.join("Cargo.toml"));
 
                 for target in target_triples {
                     cmd.args(["--target", target.as_str()]);
diff --git a/src/tools/rust-analyzer/crates/flycheck/src/test_runner.rs b/src/tools/rust-analyzer/crates/flycheck/src/test_runner.rs
index 31378716b3e..9f761c9ead1 100644
--- a/src/tools/rust-analyzer/crates/flycheck/src/test_runner.rs
+++ b/src/tools/rust-analyzer/crates/flycheck/src/test_runner.rs
@@ -55,13 +55,16 @@ pub struct CargoTestHandle {
 }
 
 // Example of a cargo test command:
-// cargo test -- module::func -Z unstable-options --format=json
+// cargo test --workspace --no-fail-fast -- module::func -Z unstable-options --format=json
 
 impl CargoTestHandle {
     pub fn new(path: Option<&str>) -> std::io::Result<Self> {
         let mut cmd = Command::new(Tool::Cargo.path());
         cmd.env("RUSTC_BOOTSTRAP", "1");
         cmd.arg("test");
+        cmd.arg("--workspace");
+        // --no-fail-fast is needed to ensure that all requested tests will run
+        cmd.arg("--no-fail-fast");
         cmd.arg("--");
         if let Some(path) = path {
             cmd.arg(path);
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
index 21536098b82..fa7730f302e 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
@@ -148,12 +148,12 @@ impl Attrs {
         }
     }
 
-    pub fn lang(&self) -> Option<&SmolStr> {
+    pub fn lang(&self) -> Option<&str> {
         self.by_key("lang").string_value()
     }
 
     pub fn lang_item(&self) -> Option<LangItem> {
-        self.by_key("lang").string_value().and_then(|it| LangItem::from_str(it))
+        self.by_key("lang").string_value().and_then(LangItem::from_str)
     }
 
     pub fn has_doc_hidden(&self) -> bool {
@@ -178,7 +178,7 @@ impl Attrs {
         self.doc_exprs().flat_map(|doc_expr| doc_expr.aliases().to_vec())
     }
 
-    pub fn export_name(&self) -> Option<&SmolStr> {
+    pub fn export_name(&self) -> Option<&str> {
         self.by_key("export_name").string_value()
     }
 
@@ -565,7 +565,7 @@ impl<'attr> AttrQuery<'attr> {
         self.attrs().filter_map(|attr| attr.token_tree_value())
     }
 
-    pub fn string_value(self) -> Option<&'attr SmolStr> {
+    pub fn string_value(self) -> Option<&'attr str> {
         self.attrs().find_map(|attr| attr.string_value())
     }
 
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 b815c9b73ef..da790f11516 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
@@ -453,8 +453,8 @@ impl ProcMacroData {
             (
                 def.name,
                 match def.kind {
-                    ProcMacroKind::CustomDerive { helpers } => Some(helpers),
-                    ProcMacroKind::FnLike | ProcMacroKind::Attr => None,
+                    ProcMacroKind::Derive { helpers } => Some(helpers),
+                    ProcMacroKind::Bang | ProcMacroKind::Attr => None,
                 },
             )
         } else {
@@ -484,10 +484,11 @@ impl ExternCrateDeclData {
         let extern_crate = &item_tree[loc.id.value];
 
         let name = extern_crate.name.clone();
+        let krate = loc.container.krate();
         let crate_id = if name == hir_expand::name![self] {
-            Some(loc.container.krate())
+            Some(krate)
         } else {
-            db.crate_def_map(loc.container.krate())
+            db.crate_def_map(krate)
                 .extern_prelude()
                 .find(|&(prelude_name, ..)| *prelude_name == name)
                 .map(|(_, (root, _))| root.krate())
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
index 1d2c7c3a55f..4638b377197 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
@@ -22,8 +22,8 @@ use crate::{
     lower::LowerCtx,
     nameres::{DefMap, MacroSubNs},
     type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRef},
-    AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LocalTypeOrConstParamId, Lookup,
-    TypeOrConstParamId, TypeParamId,
+    AdtId, ConstParamId, GenericDefId, HasModule, ItemTreeLoc, LifetimeParamId,
+    LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
 };
 
 /// Data about a generic type parameter (to a function, struct, impl, ...).
@@ -102,6 +102,52 @@ impl TypeOrConstParamData {
 
 impl_from!(TypeParamData, ConstParamData for TypeOrConstParamData);
 
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub enum GenericParamData {
+    TypeParamData(TypeParamData),
+    ConstParamData(ConstParamData),
+    LifetimeParamData(LifetimeParamData),
+}
+
+impl GenericParamData {
+    pub fn name(&self) -> Option<&Name> {
+        match self {
+            GenericParamData::TypeParamData(it) => it.name.as_ref(),
+            GenericParamData::ConstParamData(it) => Some(&it.name),
+            GenericParamData::LifetimeParamData(it) => Some(&it.name),
+        }
+    }
+
+    pub fn type_param(&self) -> Option<&TypeParamData> {
+        match self {
+            GenericParamData::TypeParamData(it) => Some(it),
+            _ => None,
+        }
+    }
+
+    pub fn const_param(&self) -> Option<&ConstParamData> {
+        match self {
+            GenericParamData::ConstParamData(it) => Some(it),
+            _ => None,
+        }
+    }
+
+    pub fn lifetime_param(&self) -> Option<&LifetimeParamData> {
+        match self {
+            GenericParamData::LifetimeParamData(it) => Some(it),
+            _ => None,
+        }
+    }
+}
+
+impl_from!(TypeParamData, ConstParamData, LifetimeParamData for GenericParamData);
+
+pub enum GenericParamDataRef<'a> {
+    TypeParamData(&'a TypeParamData),
+    ConstParamData(&'a ConstParamData),
+    LifetimeParamData(&'a LifetimeParamData),
+}
+
 /// Data about the generic parameters of a function, struct, impl, etc.
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
 pub struct GenericParams {
@@ -358,6 +404,15 @@ impl GenericParamsCollector {
 }
 
 impl GenericParams {
+    /// Number of Generic parameters (type_or_consts + lifetimes)
+    pub fn len(&self) -> usize {
+        self.type_or_consts.len() + self.lifetimes.len()
+    }
+
+    pub fn is_empty(&self) -> bool {
+        self.len() == 0
+    }
+
     /// Iterator of type_or_consts field
     pub fn iter(
         &self,
@@ -365,6 +420,13 @@ impl GenericParams {
         self.type_or_consts.iter()
     }
 
+    /// Iterator of lifetimes field
+    pub fn iter_lt(
+        &self,
+    ) -> impl DoubleEndedIterator<Item = (Idx<LifetimeParamData>, &LifetimeParamData)> {
+        self.lifetimes.iter()
+    }
+
     pub(crate) fn generic_params_query(
         db: &dyn DefDatabase,
         def: GenericDefId,
@@ -507,4 +569,18 @@ impl GenericParams {
             .then(|| id)
         })
     }
+
+    pub fn find_lifetime_by_name(
+        &self,
+        name: &Name,
+        parent: GenericDefId,
+    ) -> Option<LifetimeParamId> {
+        self.lifetimes.iter().find_map(|(id, p)| {
+            if &p.name == name {
+                Some(LifetimeParamId { local_id: id, parent })
+            } else {
+                None
+            }
+        })
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
index 953bf6b85d6..0c84057950b 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
@@ -526,7 +526,7 @@ impl Printer<'_> {
     }
 
     fn print_generic_params(&mut self, params: &GenericParams) {
-        if params.type_or_consts.is_empty() && params.lifetimes.is_empty() {
+        if params.is_empty() {
             return;
         }
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
index 7d98f6cfe88..3a07c678428 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
@@ -192,7 +192,7 @@ impl LangItems {
 
 pub(crate) fn lang_attr(db: &dyn DefDatabase, item: AttrDefId) -> Option<LangItem> {
     let attrs = db.attrs(item);
-    attrs.by_key("lang").string_value().and_then(|it| LangItem::from_str(it))
+    attrs.by_key("lang").string_value().and_then(LangItem::from_str)
 }
 
 pub(crate) fn notable_traits_in_deps(
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
index 828842de7e8..46898ce542d 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
@@ -73,7 +73,7 @@ use std::{
 use base_db::{
     impl_intern_key,
     salsa::{self, impl_intern_value_trivial},
-    CrateId, Edition,
+    CrateId,
 };
 use hir_expand::{
     builtin_attr_macro::BuiltinAttrExpander,
@@ -90,7 +90,7 @@ use hir_expand::{
 use item_tree::ExternBlock;
 use la_arena::Idx;
 use nameres::DefMap;
-use span::{AstIdNode, FileAstId, FileId, SyntaxContextId};
+use span::{AstIdNode, Edition, FileAstId, FileId, SyntaxContextId};
 use stdx::impl_from;
 use syntax::{ast, AstNode};
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs
index 965f329acb9..c5c26e26bc0 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe.rs
@@ -1449,6 +1449,7 @@ ok!();
 #[test]
 fn test_new_std_matches() {
     check(
+        //- edition:2021
         r#"
 macro_rules! matches {
     ($expression:expr, $pattern:pat $(if $guard:expr)? $(,)?) => {
@@ -1481,6 +1482,90 @@ fn main() {
 }
 
 #[test]
+fn test_hygienic_pat() {
+    check(
+        r#"
+//- /new.rs crate:new deps:old edition:2015
+old::make!();
+fn main() {
+    matches!(0, 0 | 1 if true);
+}
+//- /old.rs crate:old edition:2021
+#[macro_export]
+macro_rules! make {
+    () => {
+        macro_rules! matches {
+            ($expression:expr, $pattern:pat if $guard:expr ) => {
+                match $expression {
+                    $pattern if $guard => true,
+                    _ => false
+                }
+            };
+        }
+    }
+}
+ "#,
+        expect![[r#"
+macro_rules !matches {
+    ($expression: expr, $pattern: pat if $guard: expr) = > {
+        match $expression {
+            $pattern if $guard = > true , _ = > false
+        }
+    }
+    ;
+}
+fn main() {
+    match 0 {
+        0|1 if true =>true , _=>false
+    };
+}
+"#]],
+    );
+    check(
+        r#"
+//- /new.rs crate:new deps:old edition:2021
+old::make!();
+fn main() {
+    matches/*+errors*/!(0, 0 | 1 if true);
+}
+//- /old.rs crate:old edition:2015
+#[macro_export]
+macro_rules! make {
+    () => {
+        macro_rules! matches {
+            ($expression:expr, $pattern:pat if $guard:expr ) => {
+                match $expression {
+                    $pattern if $guard => true,
+                    _ => false
+                }
+            };
+        }
+    }
+}
+ "#,
+        expect![[r#"
+macro_rules !matches {
+    ($expression: expr, $pattern: pat if $guard: expr) = > {
+        match $expression {
+            $pattern if $guard = > true , _ = > false
+        }
+    }
+    ;
+}
+fn main() {
+    /* error: unexpected token in input *//* parse error: expected expression */
+/* parse error: expected FAT_ARROW */
+/* parse error: expected `,` */
+/* parse error: expected pattern */
+match 0 {
+        0 if $guard=>true , _=>false
+    };
+}
+"#]],
+    );
+}
+
+#[test]
 fn test_dollar_crate_lhs_is_not_meta() {
     check(
         r#"
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
index b56dee3efb5..a528c4cc697 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
@@ -59,14 +59,14 @@ mod tests;
 
 use std::ops::Deref;
 
-use base_db::{CrateId, Edition, FileId};
+use base_db::{CrateId, FileId};
 use hir_expand::{
     name::Name, proc_macro::ProcMacroKind, ErasedAstId, HirFileId, InFile, MacroCallId, MacroDefId,
 };
 use itertools::Itertools;
 use la_arena::Arena;
 use rustc_hash::{FxHashMap, FxHashSet};
-use span::{FileAstId, ROOT_ERASED_FILE_AST_ID};
+use span::{Edition, FileAstId, ROOT_ERASED_FILE_AST_ID};
 use stdx::format_to;
 use syntax::{ast, SmolStr};
 use triomphe::Arc;
@@ -737,7 +737,7 @@ impl MacroSubNs {
             MacroId::ProcMacroId(it) => {
                 return match it.lookup(db).kind {
                     ProcMacroKind::CustomDerive | ProcMacroKind::Attr => Self::Attr,
-                    ProcMacroKind::FuncLike => Self::Bang,
+                    ProcMacroKind::Bang => Self::Bang,
                 };
             }
         };
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs
index 662c80edf32..eb7f4c05ae2 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs
@@ -136,6 +136,7 @@ pub(super) fn derive_macro_as_call_id(
     call_site: SyntaxContextId,
     krate: CrateId,
     resolver: impl Fn(path::ModPath) -> Option<(MacroId, MacroDefId)>,
+    derive_macro_id: MacroCallId,
 ) -> Result<(MacroId, MacroDefId, MacroCallId), UnresolvedMacro> {
     let (macro_id, def_id) = resolver(item_attr.path.clone())
         .filter(|(_, def_id)| def_id.is_derive())
@@ -147,6 +148,7 @@ pub(super) fn derive_macro_as_call_id(
             ast_id: item_attr.ast_id,
             derive_index: derive_pos,
             derive_attr_index,
+            derive_macro_id,
         },
         call_site,
     );
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
index 3d026447fb7..ae8f028e488 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
@@ -5,7 +5,7 @@
 
 use std::{cmp::Ordering, iter, mem, ops::Not};
 
-use base_db::{CrateId, Dependency, Edition, FileId};
+use base_db::{CrateId, Dependency, FileId};
 use cfg::{CfgExpr, CfgOptions};
 use either::Either;
 use hir_expand::{
@@ -22,9 +22,9 @@ use itertools::{izip, Itertools};
 use la_arena::Idx;
 use limit::Limit;
 use rustc_hash::{FxHashMap, FxHashSet};
-use span::{ErasedFileAstId, FileAstId, Span, SyntaxContextId};
+use span::{Edition, ErasedFileAstId, FileAstId, Span, SyntaxContextId};
 use stdx::always;
-use syntax::{ast, SmolStr};
+use syntax::ast;
 use triomphe::Arc;
 
 use crate::{
@@ -237,6 +237,8 @@ enum MacroDirectiveKind {
         derive_attr: AttrId,
         derive_pos: usize,
         ctxt: SyntaxContextId,
+        /// The "parent" macro it is resolved to.
+        derive_macro_id: MacroCallId,
     },
     Attr {
         ast_id: AstIdWithPath<ast::Item>,
@@ -312,7 +314,7 @@ impl DefCollector<'_> {
                     }
                 }
                 () if *attr_name == hir_expand::name![crate_type] => {
-                    if let Some("proc-macro") = attr.string_value().map(SmolStr::as_str) {
+                    if let Some("proc-macro") = attr.string_value() {
                         self.is_proc_macro = true;
                     }
                 }
@@ -602,7 +604,7 @@ impl DefCollector<'_> {
         .intern(self.db);
         self.define_proc_macro(def.name.clone(), proc_macro_id);
         let crate_data = Arc::get_mut(&mut self.def_map.data).unwrap();
-        if let ProcMacroKind::CustomDerive { helpers } = def.kind {
+        if let ProcMacroKind::Derive { helpers } = def.kind {
             crate_data.exported_derives.insert(self.db.macro_def(proc_macro_id.into()), helpers);
         }
         crate_data.fn_proc_macro_mapping.insert(fn_id, proc_macro_id);
@@ -1146,7 +1148,13 @@ impl DefCollector<'_> {
                         return Resolved::Yes;
                     }
                 }
-                MacroDirectiveKind::Derive { ast_id, derive_attr, derive_pos, ctxt: call_site } => {
+                MacroDirectiveKind::Derive {
+                    ast_id,
+                    derive_attr,
+                    derive_pos,
+                    ctxt: call_site,
+                    derive_macro_id,
+                } => {
                     let id = derive_macro_as_call_id(
                         self.db,
                         ast_id,
@@ -1155,6 +1163,7 @@ impl DefCollector<'_> {
                         *call_site,
                         self.def_map.krate,
                         resolver,
+                        *derive_macro_id,
                     );
 
                     if let Ok((macro_id, def_id, call_id)) = id {
@@ -1224,6 +1233,8 @@ impl DefCollector<'_> {
                         _ => return Resolved::No,
                     };
 
+                    let call_id =
+                        attr_macro_as_call_id(self.db, file_ast_id, attr, self.def_map.krate, def);
                     if let MacroDefId {
                         kind:
                             MacroDefKind::BuiltInAttr(
@@ -1252,6 +1263,7 @@ impl DefCollector<'_> {
                                 return recollect_without(self);
                             }
                         };
+
                         let ast_id = ast_id.with_value(ast_adt_id);
 
                         match attr.parse_path_comma_token_tree(self.db.upcast()) {
@@ -1267,6 +1279,7 @@ impl DefCollector<'_> {
                                             derive_attr: attr.id,
                                             derive_pos: idx,
                                             ctxt: call_site.ctx,
+                                            derive_macro_id: call_id,
                                         },
                                         container: directive.container,
                                     });
@@ -1301,10 +1314,6 @@ impl DefCollector<'_> {
                         return recollect_without(self);
                     }
 
-                    // Not resolved to a derive helper or the derive attribute, so try to treat as a normal attribute.
-                    let call_id =
-                        attr_macro_as_call_id(self.db, file_ast_id, attr, self.def_map.krate, def);
-
                     // Skip #[test]/#[bench] expansion, which would merely result in more memory usage
                     // due to duplicating functions into macro expansions
                     if matches!(
@@ -1460,13 +1469,20 @@ impl DefCollector<'_> {
                         ));
                     }
                 }
-                MacroDirectiveKind::Derive { ast_id, derive_attr, derive_pos, ctxt: _ } => {
+                MacroDirectiveKind::Derive {
+                    ast_id,
+                    derive_attr,
+                    derive_pos,
+                    derive_macro_id,
+                    ..
+                } => {
                     self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
                         directive.module_id,
                         MacroCallKind::Derive {
                             ast_id: ast_id.ast_id,
                             derive_attr_index: *derive_attr,
                             derive_index: *derive_pos as u32,
+                            derive_macro_id: *derive_macro_id,
                         },
                         ast_id.path.clone(),
                     ));
@@ -1902,7 +1918,7 @@ impl ModCollector<'_, '_> {
     }
 
     fn collect_module(&mut self, module_id: FileItemTreeId<Mod>, attrs: &Attrs) {
-        let path_attr = attrs.by_key("path").string_value().map(SmolStr::as_str);
+        let path_attr = attrs.by_key("path").string_value();
         let is_macro_use = attrs.by_key("macro_use").exists();
         let module = &self.item_tree[module_id];
         match &module.kind {
@@ -2146,7 +2162,7 @@ impl ModCollector<'_, '_> {
                 Some(it) => {
                     // FIXME: a hacky way to create a Name from string.
                     name = tt::Ident {
-                        text: it.clone(),
+                        text: it.into(),
                         span: Span {
                             range: syntax::TextRange::empty(syntax::TextSize::new(0)),
                             anchor: span::SpanAnchor {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
index 9e53b037283..ee29b89f3d3 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
@@ -10,8 +10,8 @@
 //!
 //! `ReachedFixedPoint` signals about this.
 
-use base_db::Edition;
 use hir_expand::{name::Name, Lookup};
+use span::Edition;
 use triomphe::Arc;
 
 use crate::{
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/proc_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/proc_macro.rs
index c126fdac1c6..5052708dc93 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/proc_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/proc_macro.rs
@@ -13,18 +13,16 @@ pub struct ProcMacroDef {
 
 #[derive(Debug, PartialEq, Eq)]
 pub enum ProcMacroKind {
-    CustomDerive { helpers: Box<[Name]> },
-    FnLike,
+    Derive { helpers: Box<[Name]> },
+    Bang,
     Attr,
 }
 
 impl ProcMacroKind {
     pub(super) fn to_basedb_kind(&self) -> hir_expand::proc_macro::ProcMacroKind {
         match self {
-            ProcMacroKind::CustomDerive { .. } => {
-                hir_expand::proc_macro::ProcMacroKind::CustomDerive
-            }
-            ProcMacroKind::FnLike => hir_expand::proc_macro::ProcMacroKind::FuncLike,
+            ProcMacroKind::Derive { .. } => hir_expand::proc_macro::ProcMacroKind::CustomDerive,
+            ProcMacroKind::Bang => hir_expand::proc_macro::ProcMacroKind::Bang,
             ProcMacroKind::Attr => hir_expand::proc_macro::ProcMacroKind::Attr,
         }
     }
@@ -34,13 +32,13 @@ impl Attrs {
     #[rustfmt::skip]
     pub fn parse_proc_macro_decl(&self, func_name: &Name) -> Option<ProcMacroDef> {
         if self.is_proc_macro() {
-            Some(ProcMacroDef { name: func_name.clone(), kind: ProcMacroKind::FnLike })
+            Some(ProcMacroDef { name: func_name.clone(), kind: ProcMacroKind::Bang })
         } else if self.is_proc_macro_attribute() {
             Some(ProcMacroDef { name: func_name.clone(), kind: ProcMacroKind::Attr })
         } else if self.by_key("proc_macro_derive").exists() {
             let derive = self.by_key("proc_macro_derive").tt_values().next()?;
             let def = parse_macro_name_and_helper_attrs(&derive.token_trees)
-                .map(|(name, helpers)| ProcMacroDef { name, kind: ProcMacroKind::CustomDerive { helpers } });
+                .map(|(name, helpers)| ProcMacroDef { name, kind: ProcMacroKind::Derive { helpers } });
 
             if def.is_none() {
                 tracing::trace!("malformed `#[proc_macro_derive]`: {}", derive);
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
index 226d6f513f5..fadab858aa1 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
@@ -24,6 +24,7 @@ use crate::{
     nameres::{DefMap, MacroSubNs},
     path::{ModPath, Path, PathKind},
     per_ns::PerNs,
+    type_ref::LifetimeRef,
     visibility::{RawVisibility, Visibility},
     AdtId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId,
     ExternBlockId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId,
@@ -120,6 +121,12 @@ pub enum ValueNs {
     GenericParam(ConstParamId),
 }
 
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum LifetimeNs {
+    Static,
+    LifetimeParam(LifetimeParamId),
+}
+
 impl Resolver {
     /// Resolve known trait from std, like `std::futures::Future`
     pub fn resolve_known_trait(&self, db: &dyn DefDatabase, path: &ModPath) -> Option<TraitId> {
@@ -418,6 +425,19 @@ impl Resolver {
         self.resolve_path_as_macro(db, path, expected_macro_kind).map(|(it, _)| db.macro_def(it))
     }
 
+    pub fn resolve_lifetime(&self, lifetime: &LifetimeRef) -> Option<LifetimeNs> {
+        if lifetime.name == name::known::STATIC_LIFETIME {
+            return Some(LifetimeNs::Static);
+        }
+
+        self.scopes().find_map(|scope| match scope {
+            Scope::GenericParams { def, params } => {
+                params.find_lifetime_by_name(&lifetime.name, *def).map(LifetimeNs::LifetimeParam)
+            }
+            _ => None,
+        })
+    }
+
     /// Returns a set of names available in the current scope.
     ///
     /// Note that this is a somewhat fuzzy concept -- internally, the compiler
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs
index af3ecdcd5e3..f1540498f26 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs
@@ -8,8 +8,8 @@ use intern::Interned;
 use mbe::{syntax_node_to_token_tree, DelimiterKind, Punct};
 use smallvec::{smallvec, SmallVec};
 use span::{Span, SyntaxContextId};
-use syntax::{ast, match_ast, AstNode, AstToken, SmolStr, SyntaxNode};
-use triomphe::Arc;
+use syntax::{ast, format_smolstr, match_ast, AstNode, AstToken, SmolStr, SyntaxNode};
+use triomphe::ThinArc;
 
 use crate::{
     db::ExpandDatabase,
@@ -22,8 +22,7 @@ use crate::{
 /// Syntactical attributes, without filtering of `cfg_attr`s.
 #[derive(Default, Debug, Clone, PartialEq, Eq)]
 pub struct RawAttrs {
-    // FIXME: Make this a ThinArc
-    entries: Option<Arc<[Attr]>>,
+    entries: Option<ThinArc<(), Attr>>,
 }
 
 impl ops::Deref for RawAttrs {
@@ -31,7 +30,7 @@ impl ops::Deref for RawAttrs {
 
     fn deref(&self) -> &[Attr] {
         match &self.entries {
-            Some(it) => it,
+            Some(it) => &it.slice,
             None => &[],
         }
     }
@@ -45,20 +44,34 @@ impl RawAttrs {
         owner: &dyn ast::HasAttrs,
         span_map: SpanMapRef<'_>,
     ) -> Self {
-        let entries = collect_attrs(owner).filter_map(|(id, attr)| match attr {
-            Either::Left(attr) => {
-                attr.meta().and_then(|meta| Attr::from_src(db, meta, span_map, id))
-            }
-            Either::Right(comment) => comment.doc_comment().map(|doc| Attr {
-                id,
-                input: Some(Interned::new(AttrInput::Literal(SmolStr::new(doc)))),
-                path: Interned::new(ModPath::from(crate::name!(doc))),
-                ctxt: span_map.span_for_range(comment.syntax().text_range()).ctx,
-            }),
-        });
-        let entries: Arc<[Attr]> = Arc::from_iter(entries);
+        let entries: Vec<_> = collect_attrs(owner)
+            .filter_map(|(id, attr)| match attr {
+                Either::Left(attr) => {
+                    attr.meta().and_then(|meta| Attr::from_src(db, meta, span_map, id))
+                }
+                Either::Right(comment) => comment.doc_comment().map(|doc| {
+                    let span = span_map.span_for_range(comment.syntax().text_range());
+                    Attr {
+                        id,
+                        input: Some(Interned::new(AttrInput::Literal(tt::Literal {
+                            // FIXME: Escape quotes from comment content
+                            text: SmolStr::new(format_smolstr!("\"{doc}\"",)),
+                            span,
+                        }))),
+                        path: Interned::new(ModPath::from(crate::name!(doc))),
+                        ctxt: span.ctx,
+                    }
+                }),
+            })
+            .collect();
 
-        Self { entries: if entries.is_empty() { None } else { Some(entries) } }
+        let entries = if entries.is_empty() {
+            None
+        } else {
+            Some(ThinArc::from_header_and_iter((), entries.into_iter()))
+        };
+
+        RawAttrs { entries }
     }
 
     pub fn from_attrs_owner(
@@ -75,16 +88,20 @@ impl RawAttrs {
             (None, entries @ Some(_)) => Self { entries },
             (Some(entries), None) => Self { entries: Some(entries.clone()) },
             (Some(a), Some(b)) => {
-                let last_ast_index = a.last().map_or(0, |it| it.id.ast_index() + 1) as u32;
-                Self {
-                    entries: Some(Arc::from_iter(a.iter().cloned().chain(b.iter().map(|it| {
+                let last_ast_index = a.slice.last().map_or(0, |it| it.id.ast_index() + 1) as u32;
+                let items = a
+                    .slice
+                    .iter()
+                    .cloned()
+                    .chain(b.slice.iter().map(|it| {
                         let mut it = it.clone();
                         it.id.id = (it.id.ast_index() as u32 + last_ast_index)
                             | (it.id.cfg_attr_index().unwrap_or(0) as u32)
                                 << AttrId::AST_INDEX_BITS;
                         it
-                    })))),
-                }
+                    }))
+                    .collect::<Vec<_>>();
+                Self { entries: Some(ThinArc::from_header_and_iter((), items.into_iter())) }
             }
         }
     }
@@ -100,41 +117,47 @@ impl RawAttrs {
         }
 
         let crate_graph = db.crate_graph();
-        let new_attrs = Arc::from_iter(self.iter().flat_map(|attr| -> SmallVec<[_; 1]> {
-            let is_cfg_attr =
-                attr.path.as_ident().map_or(false, |name| *name == crate::name![cfg_attr]);
-            if !is_cfg_attr {
-                return smallvec![attr.clone()];
-            }
-
-            let subtree = match attr.token_tree_value() {
-                Some(it) => it,
-                _ => return smallvec![attr.clone()],
-            };
-
-            let (cfg, parts) = match parse_cfg_attr_input(subtree) {
-                Some(it) => it,
-                None => return smallvec![attr.clone()],
-            };
-            let index = attr.id;
-            let attrs = parts
-                .enumerate()
-                .take(1 << AttrId::CFG_ATTR_BITS)
-                .filter_map(|(idx, attr)| Attr::from_tt(db, attr, index.with_cfg_attr(idx)));
-
-            let cfg_options = &crate_graph[krate].cfg_options;
-            let cfg = Subtree { delimiter: subtree.delimiter, token_trees: Box::from(cfg) };
-            let cfg = CfgExpr::parse(&cfg);
-            if cfg_options.check(&cfg) == Some(false) {
-                smallvec![]
-            } else {
-                cov_mark::hit!(cfg_attr_active);
-
-                attrs.collect()
-            }
-        }));
+        let new_attrs =
+            self.iter()
+                .flat_map(|attr| -> SmallVec<[_; 1]> {
+                    let is_cfg_attr =
+                        attr.path.as_ident().map_or(false, |name| *name == crate::name![cfg_attr]);
+                    if !is_cfg_attr {
+                        return smallvec![attr.clone()];
+                    }
 
-        RawAttrs { entries: Some(new_attrs) }
+                    let subtree = match attr.token_tree_value() {
+                        Some(it) => it,
+                        _ => return smallvec![attr.clone()],
+                    };
+
+                    let (cfg, parts) = match parse_cfg_attr_input(subtree) {
+                        Some(it) => it,
+                        None => return smallvec![attr.clone()],
+                    };
+                    let index = attr.id;
+                    let attrs = parts.enumerate().take(1 << AttrId::CFG_ATTR_BITS).filter_map(
+                        |(idx, attr)| Attr::from_tt(db, attr, index.with_cfg_attr(idx)),
+                    );
+
+                    let cfg_options = &crate_graph[krate].cfg_options;
+                    let cfg = Subtree { delimiter: subtree.delimiter, token_trees: Box::from(cfg) };
+                    let cfg = CfgExpr::parse(&cfg);
+                    if cfg_options.check(&cfg) == Some(false) {
+                        smallvec![]
+                    } else {
+                        cov_mark::hit!(cfg_attr_active);
+
+                        attrs.collect()
+                    }
+                })
+                .collect::<Vec<_>>();
+        let entries = if new_attrs.is_empty() {
+            None
+        } else {
+            Some(ThinArc::from_header_and_iter((), new_attrs.into_iter()))
+        };
+        RawAttrs { entries }
     }
 }
 
@@ -179,8 +202,7 @@ pub struct Attr {
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum AttrInput {
     /// `#[attr = "string"]`
-    // FIXME: This is losing span
-    Literal(SmolStr),
+    Literal(tt::Literal),
     /// `#[attr(subtree)]`
     TokenTree(Box<tt::Subtree>),
 }
@@ -188,7 +210,7 @@ pub enum AttrInput {
 impl fmt::Display for AttrInput {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
-            AttrInput::Literal(lit) => write!(f, " = \"{}\"", lit.escape_debug()),
+            AttrInput::Literal(lit) => write!(f, " = {lit}"),
             AttrInput::TokenTree(tt) => tt.fmt(f),
         }
     }
@@ -208,11 +230,10 @@ impl Attr {
         })?);
         let span = span_map.span_for_range(range);
         let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() {
-            let value = match lit.kind() {
-                ast::LiteralKind::String(string) => string.value()?.into(),
-                _ => lit.syntax().first_token()?.text().trim_matches('"').into(),
-            };
-            Some(Interned::new(AttrInput::Literal(value)))
+            Some(Interned::new(AttrInput::Literal(tt::Literal {
+                text: lit.token().text().into(),
+                span,
+            })))
         } else if let Some(tt) = ast.token_tree() {
             let tree = syntax_node_to_token_tree(tt.syntax(), span_map, span);
             Some(Interned::new(AttrInput::TokenTree(Box::new(tree))))
@@ -245,9 +266,8 @@ impl Attr {
             }
             Some(tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: '=', .. }))) => {
                 let input = match input.get(1) {
-                    Some(tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { text, .. }))) => {
-                        //FIXME the trimming here isn't quite right, raw strings are not handled
-                        Some(Interned::new(AttrInput::Literal(text.trim_matches('"').into())))
+                    Some(tt::TokenTree::Leaf(tt::Leaf::Literal(lit))) => {
+                        Some(Interned::new(AttrInput::Literal(lit.clone())))
                     }
                     _ => None,
                 };
@@ -265,9 +285,14 @@ impl Attr {
 
 impl Attr {
     /// #[path = "string"]
-    pub fn string_value(&self) -> Option<&SmolStr> {
+    pub fn string_value(&self) -> Option<&str> {
         match self.input.as_deref()? {
-            AttrInput::Literal(it) => Some(it),
+            AttrInput::Literal(it) => match it.text.strip_prefix('r') {
+                Some(it) => it.trim_matches('#'),
+                None => it.text.as_str(),
+            }
+            .strip_prefix('"')?
+            .strip_suffix('"'),
             _ => None,
         }
     }
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs
index 9fb6a0b2346..fd3e4e7a4db 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs
@@ -1,11 +1,11 @@
 //! Builtin macro
 
-use base_db::{AnchoredPath, Edition, FileId};
+use base_db::{AnchoredPath, FileId};
 use cfg::CfgExpr;
 use either::Either;
 use itertools::Itertools;
 use mbe::{parse_exprs_with_sep, parse_to_token_tree};
-use span::{Span, SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID};
+use span::{Edition, Span, SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID};
 use syntax::ast::{self, AstToken};
 
 use crate::{
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs b/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs
index c74c13a6fd3..db3558a84e9 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/cfg_process.rs
@@ -10,7 +10,7 @@ use syntax::{
 use tracing::{debug, warn};
 use tt::SmolStr;
 
-use crate::{db::ExpandDatabase, MacroCallKind, MacroCallLoc};
+use crate::{db::ExpandDatabase, proc_macro::ProcMacroKind, MacroCallLoc, MacroDefKind};
 
 fn check_cfg_attr(attr: &Attr, loc: &MacroCallLoc, db: &dyn ExpandDatabase) -> Option<bool> {
     if !attr.simple_name().as_deref().map(|v| v == "cfg")? {
@@ -139,7 +139,7 @@ fn process_enum(
     'variant: for variant in variants.variants() {
         for attr in variant.attrs() {
             if check_cfg_attr(&attr, loc, db).map(|enabled| !enabled).unwrap_or_default() {
-                // Rustc does not strip the attribute if it is enabled. So we will will leave it
+                // Rustc does not strip the attribute if it is enabled. So we will leave it
                 debug!("censoring type {:?}", variant.syntax());
                 remove.insert(variant.syntax().clone().into());
                 // We need to remove the , as well
@@ -180,7 +180,13 @@ pub(crate) fn process_cfg_attrs(
     db: &dyn ExpandDatabase,
 ) -> Option<FxHashSet<SyntaxElement>> {
     // FIXME: #[cfg_eval] is not implemented. But it is not stable yet
-    if !matches!(loc.kind, MacroCallKind::Derive { .. }) {
+    let is_derive = match loc.def.kind {
+        MacroDefKind::BuiltInDerive(..)
+        | MacroDefKind::ProcMacro(_, ProcMacroKind::CustomDerive, _) => true,
+        MacroDefKind::BuiltInAttr(expander, _) => expander.is_derive(),
+        _ => false,
+    };
+    if !is_derive {
         return None;
     }
     let mut remove = FxHashSet::default();
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
index ec68f2f96e5..5461c1c49a3 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
@@ -24,7 +24,8 @@ use crate::{
     HirFileId, HirFileIdRepr, MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind,
     MacroFileId,
 };
-
+/// This is just to ensure the types of smart_macro_arg and macro_arg are the same
+type MacroArgResult = (Arc<tt::Subtree>, SyntaxFixupUndoInfo, Span);
 /// Total limit on the number of tokens produced by any macro invocation.
 ///
 /// If an invocation produces more tokens than this limit, it will not be stored in the database and
@@ -98,7 +99,13 @@ pub trait ExpandDatabase: SourceDatabase {
     /// Lowers syntactic macro call to a token tree representation. That's a firewall
     /// query, only typing in the macro call itself changes the returned
     /// subtree.
-    fn macro_arg(&self, id: MacroCallId) -> (Arc<tt::Subtree>, SyntaxFixupUndoInfo, Span);
+    fn macro_arg(&self, id: MacroCallId) -> MacroArgResult;
+    #[salsa::transparent]
+    fn macro_arg_considering_derives(
+        &self,
+        id: MacroCallId,
+        kind: &MacroCallKind,
+    ) -> MacroArgResult;
     /// Fetches the expander for this macro.
     #[salsa::transparent]
     #[salsa::invoke(TokenExpander::macro_expander)]
@@ -144,7 +151,7 @@ pub fn expand_speculative(
     let span_map = RealSpanMap::absolute(FileId::BOGUS);
     let span_map = SpanMapRef::RealSpanMap(&span_map);
 
-    let (_, _, span) = db.macro_arg(actual_macro_call);
+    let (_, _, span) = db.macro_arg_considering_derives(actual_macro_call, &loc.kind);
 
     // Build the subtree and token mapping for the speculative args
     let (mut tt, undo_info) = match loc.kind {
@@ -339,12 +346,24 @@ pub(crate) fn parse_with_map(
     }
 }
 
-// FIXME: for derive attributes, this will return separate copies of the same structures! Though
-// they may differ in spans due to differing call sites...
-fn macro_arg(
+/// This resolves the [MacroCallId] to check if it is a derive macro if so get the [macro_arg] for the derive.
+/// Other wise return the [macro_arg] for the macro_call_id.
+///
+/// This is not connected to the database so it does not cached the result. However, the inner [macro_arg] query is
+fn macro_arg_considering_derives(
     db: &dyn ExpandDatabase,
     id: MacroCallId,
-) -> (Arc<tt::Subtree>, SyntaxFixupUndoInfo, Span) {
+    kind: &MacroCallKind,
+) -> MacroArgResult {
+    match kind {
+        // Get the macro arg for the derive macro
+        MacroCallKind::Derive { derive_macro_id, .. } => db.macro_arg(*derive_macro_id),
+        // Normal macro arg
+        _ => db.macro_arg(id),
+    }
+}
+
+fn macro_arg(db: &dyn ExpandDatabase, id: MacroCallId) -> MacroArgResult {
     let loc = db.lookup_intern_macro_call(id);
 
     if let MacroCallLoc {
@@ -414,29 +433,30 @@ fn macro_arg(
             }
             return (Arc::new(tt), SyntaxFixupUndoInfo::NONE, span);
         }
-        MacroCallKind::Derive { ast_id, derive_attr_index, .. } => {
-            let node = ast_id.to_ptr(db).to_node(&root);
-            let censor_derive_input = censor_derive_input(derive_attr_index, &node);
-            let item_node = node.into();
-            let attr_source = attr_source(derive_attr_index, &item_node);
-            // FIXME: This is wrong, this should point to the path of the derive attribute`
-            let span =
-                map.span_for_range(attr_source.as_ref().and_then(|it| it.path()).map_or_else(
-                    || item_node.syntax().text_range(),
-                    |it| it.syntax().text_range(),
-                ));
-            (censor_derive_input, item_node, span)
+        // MacroCallKind::Derive should not be here. As we are getting the argument for the derive macro
+        MacroCallKind::Derive { .. } => {
+            unreachable!("`ExpandDatabase::macro_arg` called with `MacroCallKind::Derive`")
         }
         MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => {
             let node = ast_id.to_ptr(db).to_node(&root);
             let attr_source = attr_source(invoc_attr_index, &node);
+
             let span = map.span_for_range(
                 attr_source
                     .as_ref()
                     .and_then(|it| it.path())
                     .map_or_else(|| node.syntax().text_range(), |it| it.syntax().text_range()),
             );
-            (attr_source.into_iter().map(|it| it.syntax().clone().into()).collect(), node, span)
+            // If derive attribute we need to censor the derive input
+            if matches!(loc.def.kind, MacroDefKind::BuiltInAttr(expander, ..) if expander.is_derive())
+                && ast::Adt::can_cast(node.syntax().kind())
+            {
+                let adt = ast::Adt::cast(node.syntax().clone()).unwrap();
+                let censor_derive_input = censor_derive_input(invoc_attr_index, &adt);
+                (censor_derive_input, node, span)
+            } else {
+                (attr_source.into_iter().map(|it| it.syntax().clone().into()).collect(), node, span)
+            }
         }
     };
 
@@ -526,7 +546,8 @@ fn macro_expand(
     let (ExpandResult { value: tt, err }, span) = match loc.def.kind {
         MacroDefKind::ProcMacro(..) => return db.expand_proc_macro(macro_call_id).map(CowArc::Arc),
         _ => {
-            let (macro_arg, undo_info, span) = db.macro_arg(macro_call_id);
+            let (macro_arg, undo_info, span) =
+                db.macro_arg_considering_derives(macro_call_id, &loc.kind);
 
             let arg = &*macro_arg;
             let res =
@@ -603,7 +624,7 @@ fn proc_macro_span(db: &dyn ExpandDatabase, ast: AstId<ast::Fn>) -> Span {
 
 fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt::Subtree>> {
     let loc = db.lookup_intern_macro_call(id);
-    let (macro_arg, undo_info, span) = db.macro_arg(id);
+    let (macro_arg, undo_info, span) = db.macro_arg_considering_derives(id, &loc.kind);
 
     let (expander, ast) = match loc.def.kind {
         MacroDefKind::ProcMacro(expander, _, ast) => (expander, ast),
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs
index 33643c02724..9a0b218e6d1 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs
@@ -1,8 +1,8 @@
 //! Compiled declarative macro expanders (`macro_rules!`` and `macro`)
 use std::sync::OnceLock;
 
-use base_db::{CrateId, Edition, VersionReq};
-use span::{MacroCallId, Span};
+use base_db::{CrateId, VersionReq};
+use span::{MacroCallId, Span, SyntaxContextId};
 use syntax::{ast, AstNode};
 use triomphe::Arc;
 
@@ -10,13 +10,13 @@ use crate::{
     attrs::RawAttrs,
     db::ExpandDatabase,
     hygiene::{apply_mark, Transparency},
-    tt, AstId, ExpandError, ExpandResult,
+    tt, AstId, ExpandError, ExpandResult, Lookup,
 };
 
 /// Old-style `macro_rules` or the new macros 2.0
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub struct DeclarativeMacroExpander {
-    pub mac: mbe::DeclarativeMacro<span::Span>,
+    pub mac: mbe::DeclarativeMacro,
     pub transparency: Transparency,
 }
 
@@ -94,8 +94,6 @@ impl DeclarativeMacroExpander {
         def_crate: CrateId,
         id: AstId<ast::Macro>,
     ) -> Arc<DeclarativeMacroExpander> {
-        let crate_data = &db.crate_graph()[def_crate];
-        let is_2021 = crate_data.edition >= Edition::Edition2021;
         let (root, map) = crate::db::parse_with_map(db, id.file_id);
         let root = root.syntax_node();
 
@@ -133,6 +131,16 @@ impl DeclarativeMacroExpander {
             )
         });
 
+        let edition = |ctx: SyntaxContextId| {
+            let crate_graph = db.crate_graph();
+            if ctx.is_root() {
+                crate_graph[def_crate].edition
+            } else {
+                let data = db.lookup_intern_syntax_context(ctx);
+                // UNWRAP-SAFETY: Only the root context has no outer expansion
+                crate_graph[data.outer_expn.unwrap().lookup(db).def.krate].edition
+            }
+        };
         let (mac, transparency) = match id.to_ptr(db).to_node(&root) {
             ast::Macro::MacroRules(macro_rules) => (
                 match macro_rules.token_tree() {
@@ -145,12 +153,11 @@ impl DeclarativeMacroExpander {
                             ),
                         );
 
-                        mbe::DeclarativeMacro::parse_macro_rules(&tt, is_2021, new_meta_vars)
+                        mbe::DeclarativeMacro::parse_macro_rules(&tt, edition, new_meta_vars)
                     }
-                    None => mbe::DeclarativeMacro::from_err(
-                        mbe::ParseError::Expected("expected a token tree".into()),
-                        is_2021,
-                    ),
+                    None => mbe::DeclarativeMacro::from_err(mbe::ParseError::Expected(
+                        "expected a token tree".into(),
+                    )),
                 },
                 transparency(&macro_rules).unwrap_or(Transparency::SemiTransparent),
             ),
@@ -163,12 +170,11 @@ impl DeclarativeMacroExpander {
                             map.span_for_range(macro_def.macro_token().unwrap().text_range()),
                         );
 
-                        mbe::DeclarativeMacro::parse_macro2(&tt, is_2021, new_meta_vars)
+                        mbe::DeclarativeMacro::parse_macro2(&tt, edition, new_meta_vars)
                     }
-                    None => mbe::DeclarativeMacro::from_err(
-                        mbe::ParseError::Expected("expected a token tree".into()),
-                        is_2021,
-                    ),
+                    None => mbe::DeclarativeMacro::from_err(mbe::ParseError::Expected(
+                        "expected a token tree".into(),
+                    )),
                 },
                 transparency(&macro_def).unwrap_or(Transparency::Opaque),
             ),
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
index 5d4f7dc1462..db8bbeccef8 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
@@ -30,10 +30,11 @@ use triomphe::Arc;
 
 use std::{fmt, hash::Hash};
 
-use base_db::{salsa::impl_intern_value_trivial, CrateId, Edition, FileId};
+use base_db::{salsa::impl_intern_value_trivial, CrateId, FileId};
 use either::Either;
 use span::{
-    ErasedFileAstId, FileRange, HirFileIdRepr, Span, SpanAnchor, SyntaxContextData, SyntaxContextId,
+    Edition, ErasedFileAstId, FileRange, HirFileIdRepr, Span, SpanAnchor, SyntaxContextData,
+    SyntaxContextId,
 };
 use syntax::{
     ast::{self, AstNode},
@@ -53,11 +54,9 @@ use crate::{
 
 pub use crate::files::{AstId, ErasedAstId, InFile, InMacroFile, InRealFile};
 
-pub use mbe::ValueResult;
+pub use mbe::{DeclarativeMacro, ValueResult};
 pub use span::{HirFileId, MacroCallId, MacroFileId};
 
-pub type DeclarativeMacro = ::mbe::DeclarativeMacro<tt::Span>;
-
 pub mod tt {
     pub use span::Span;
     pub use tt::{DelimiterKind, Spacing};
@@ -201,7 +200,7 @@ pub struct EagerCallInfo {
     /// Call id of the eager macro's input file (this is the macro file for its fully expanded input).
     arg_id: MacroCallId,
     error: Option<ExpandError>,
-    /// TODO: Doc
+    /// The call site span of the eager macro
     span: Span,
 }
 
@@ -212,7 +211,7 @@ pub enum MacroCallKind {
         expand_to: ExpandTo,
         /// Some if this is a macro call for an eager macro. Note that this is `None`
         /// for the eager input macro file.
-        // FIXME: This is being interned, subtrees can vary quickly differ just slightly causing
+        // FIXME: This is being interned, subtrees can vary quickly differing just slightly causing
         // leakage problems here
         eager: Option<Arc<EagerCallInfo>>,
     },
@@ -225,6 +224,9 @@ pub enum MacroCallKind {
         derive_attr_index: AttrId,
         /// Index of the derive macro in the derive attribute
         derive_index: u32,
+        /// The "parent" macro call.
+        /// We will resolve the same token tree for all derive macros in the same derive attribute.
+        derive_macro_id: MacroCallId,
     },
     Attr {
         ast_id: AstId<ast::Item>,
@@ -484,7 +486,7 @@ impl MacroDefId {
         matches!(
             self.kind,
             MacroDefKind::BuiltIn(..)
-                | MacroDefKind::ProcMacro(_, ProcMacroKind::FuncLike, _)
+                | MacroDefKind::ProcMacro(_, ProcMacroKind::Bang, _)
                 | MacroDefKind::BuiltInEager(..)
                 | MacroDefKind::Declarative(..)
         )
@@ -806,7 +808,8 @@ impl ExpansionInfo {
         let (parse, exp_map) = db.parse_macro_expansion(macro_file).value;
         let expanded = InMacroFile { file_id: macro_file, value: parse.syntax_node() };
 
-        let (macro_arg, _, _) = db.macro_arg(macro_file.macro_call_id);
+        let (macro_arg, _, _) =
+            db.macro_arg_considering_derives(macro_file.macro_call_id, &loc.kind);
 
         let def = loc.def.ast_id().left().and_then(|id| {
             let def_tt = match id.to_node(db) {
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs
index fc186d2c26d..46f8c2b9d8c 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs
@@ -225,6 +225,26 @@ fn convert_path(
     let mut segments = path.segments();
 
     let segment = &segments.next()?;
+    let handle_super_kw = &mut |init_deg| {
+        let mut deg = init_deg;
+        let mut next_segment = None;
+        for segment in segments.by_ref() {
+            match segment.kind()? {
+                ast::PathSegmentKind::SuperKw => deg += 1,
+                ast::PathSegmentKind::Name(name) => {
+                    next_segment = Some(name.as_name());
+                    break;
+                }
+                ast::PathSegmentKind::Type { .. }
+                | ast::PathSegmentKind::SelfTypeKw
+                | ast::PathSegmentKind::SelfKw
+                | ast::PathSegmentKind::CrateKw => return None,
+            }
+        }
+
+        Some(ModPath::from_segments(PathKind::Super(deg), next_segment))
+    };
+
     let mut mod_path = match segment.kind()? {
         ast::PathSegmentKind::Name(name_ref) => {
             if name_ref.text() == "$crate" {
@@ -245,26 +265,8 @@ fn convert_path(
             ModPath::from_segments(PathKind::Plain, Some(known::SELF_TYPE))
         }
         ast::PathSegmentKind::CrateKw => ModPath::from_segments(PathKind::Crate, iter::empty()),
-        ast::PathSegmentKind::SelfKw => ModPath::from_segments(PathKind::Super(0), iter::empty()),
-        ast::PathSegmentKind::SuperKw => {
-            let mut deg = 1;
-            let mut next_segment = None;
-            for segment in segments.by_ref() {
-                match segment.kind()? {
-                    ast::PathSegmentKind::SuperKw => deg += 1,
-                    ast::PathSegmentKind::Name(name) => {
-                        next_segment = Some(name.as_name());
-                        break;
-                    }
-                    ast::PathSegmentKind::Type { .. }
-                    | ast::PathSegmentKind::SelfTypeKw
-                    | ast::PathSegmentKind::SelfKw
-                    | ast::PathSegmentKind::CrateKw => return None,
-                }
-            }
-
-            ModPath::from_segments(PathKind::Super(deg), next_segment)
-        }
+        ast::PathSegmentKind::SelfKw => handle_super_kw(0)?,
+        ast::PathSegmentKind::SuperKw => handle_super_kw(1)?,
         ast::PathSegmentKind::Type { .. } => {
             // not allowed in imports
             return None;
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs
index ca6fc0afe2d..abed16fecde 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs
@@ -23,7 +23,7 @@ impl ProcMacroId {
 #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
 pub enum ProcMacroKind {
     CustomDerive,
-    FuncLike,
+    Bang,
     Attr,
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
index 3cfedcdcb4d..bf473740166 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
@@ -47,13 +47,14 @@ hir-expand.workspace = true
 base-db.workspace = true
 syntax.workspace = true
 limit.workspace = true
+span.workspace = true
 
 [dev-dependencies]
 expect-test = "1.4.0"
 tracing.workspace = true
 tracing-subscriber.workspace = true
 tracing-tree.workspace = true
-project-model = { path = "../project-model" }
+project-model.workspace = true
 
 # local deps
 test-utils.workspace = true
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs b/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs
index c485c9b2e80..cb118a36848 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs
@@ -9,21 +9,21 @@ use chalk_ir::{
     AdtId, DebruijnIndex, Scalar,
 };
 use hir_def::{
-    builtin_type::BuiltinType, generics::TypeOrConstParamData, ConstParamId, DefWithBodyId,
-    GenericDefId, TraitId, TypeAliasId,
+    builtin_type::BuiltinType, DefWithBodyId, GenericDefId, GenericParamId, TraitId, TypeAliasId,
 };
 use smallvec::SmallVec;
 
 use crate::{
-    consteval::unknown_const_as_generic, db::HirDatabase, infer::unify::InferenceTable, primitive,
-    to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders, BoundVar, CallableSig,
-    GenericArg, GenericArgData, Interner, ProjectionTy, Substitution, TraitRef, Ty, TyDefId, TyExt,
-    TyKind,
+    consteval::unknown_const_as_generic, db::HirDatabase, error_lifetime,
+    infer::unify::InferenceTable, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics,
+    Binders, BoundVar, CallableSig, GenericArg, GenericArgData, Interner, ProjectionTy,
+    Substitution, TraitRef, Ty, TyDefId, TyExt, TyKind,
 };
 
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub enum ParamKind {
     Type,
+    Lifetime,
     Const(Ty),
 }
 
@@ -107,6 +107,9 @@ impl<D> TyBuilder<D> {
             ParamKind::Const(ty) => {
                 BoundVar::new(debruijn, idx).to_const(Interner, ty.clone()).cast(Interner)
             }
+            ParamKind::Lifetime => {
+                BoundVar::new(debruijn, idx).to_lifetime(Interner).cast(Interner)
+            }
         });
         this.vec.extend(filler.take(this.remaining()).casted(Interner));
         assert_eq!(this.remaining(), 0);
@@ -119,6 +122,7 @@ impl<D> TyBuilder<D> {
         let filler = this.param_kinds[this.vec.len()..].iter().map(|x| match x {
             ParamKind::Type => TyKind::Error.intern(Interner).cast(Interner),
             ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
+            ParamKind::Lifetime => error_lifetime().cast(Interner),
         });
         this.vec.extend(filler.casted(Interner));
         assert_eq!(this.remaining(), 0);
@@ -130,6 +134,7 @@ impl<D> TyBuilder<D> {
         self.fill(|x| match x {
             ParamKind::Type => table.new_type_var().cast(Interner),
             ParamKind::Const(ty) => table.new_const_var(ty.clone()).cast(Interner),
+            ParamKind::Lifetime => table.new_lifetime_var().cast(Interner),
         })
     }
 
@@ -142,7 +147,8 @@ impl<D> TyBuilder<D> {
     fn assert_match_kind(&self, a: &chalk_ir::GenericArg<Interner>, e: &ParamKind) {
         match (a.data(Interner), e) {
             (GenericArgData::Ty(_), ParamKind::Type)
-            | (GenericArgData::Const(_), ParamKind::Const(_)) => (),
+            | (GenericArgData::Const(_), ParamKind::Const(_))
+            | (GenericArgData::Lifetime(_), ParamKind::Lifetime) => (),
             _ => panic!("Mismatched kinds: {a:?}, {:?}, {:?}", self.vec, self.param_kinds),
         }
     }
@@ -201,10 +207,11 @@ impl TyBuilder<()> {
         Substitution::from_iter(
             Interner,
             params.iter_id().map(|id| match id {
-                either::Either::Left(_) => TyKind::Error.intern(Interner).cast(Interner),
-                either::Either::Right(id) => {
+                GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner),
+                GenericParamId::ConstParamId(id) => {
                     unknown_const_as_generic(db.const_param_ty(id)).cast(Interner)
                 }
+                GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner),
             }),
         )
     }
@@ -219,11 +226,10 @@ impl TyBuilder<()> {
         assert!(generics.parent_generics().is_some() == parent_subst.is_some());
         let params = generics
             .iter_self()
-            .map(|(id, data)| match data {
-                TypeOrConstParamData::TypeParamData(_) => ParamKind::Type,
-                TypeOrConstParamData::ConstParamData(_) => {
-                    ParamKind::Const(db.const_param_ty(ConstParamId::from_unchecked(id)))
-                }
+            .map(|(id, _data)| match id {
+                GenericParamId::TypeParamId(_) => ParamKind::Type,
+                GenericParamId::ConstParamId(id) => ParamKind::Const(db.const_param_ty(id)),
+                GenericParamId::LifetimeParamId(_) => ParamKind::Lifetime,
             })
             .collect();
         TyBuilder::new((), params, parent_subst)
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
index e678a2fee13..46612242b09 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
@@ -272,6 +272,19 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
                 };
                 chalk_ir::Binders::new(binders, bound)
             }
+            crate::ImplTraitId::AssociatedTypeImplTrait(alias, idx) => {
+                let datas = self
+                    .db
+                    .type_alias_impl_traits(alias)
+                    .expect("impl trait id without impl traits");
+                let (datas, binders) = (*datas).as_ref().into_value_and_skipped_binders();
+                let data = &datas.impl_traits[idx];
+                let bound = OpaqueTyDatumBound {
+                    bounds: make_single_type_binders(data.bounds.skip_binders().to_vec()),
+                    where_clauses: chalk_ir::Binders::empty(Interner, vec![]),
+                };
+                chalk_ir::Binders::new(binders, bound)
+            }
             crate::ImplTraitId::AsyncBlockTypeImplTrait(..) => {
                 if let Some((future_trait, future_output)) = self
                     .db
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs
index 795a5996912..d1aebeff261 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs
@@ -268,6 +268,13 @@ impl TyExt for Ty {
                             data.substitute(Interner, &subst).into_value_and_skipped_binders().0
                         })
                     }
+                    ImplTraitId::AssociatedTypeImplTrait(alias, idx) => {
+                        db.type_alias_impl_traits(alias).map(|it| {
+                            let data =
+                                (*it).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
+                            data.substitute(Interner, &subst).into_value_and_skipped_binders().0
+                        })
+                    }
                 }
             }
             TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
@@ -280,6 +287,13 @@ impl TyExt for Ty {
                             data.substitute(Interner, &opaque_ty.substitution)
                         })
                     }
+                    ImplTraitId::AssociatedTypeImplTrait(alias, idx) => {
+                        db.type_alias_impl_traits(alias).map(|it| {
+                            let data =
+                                (*it).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
+                            data.substitute(Interner, &opaque_ty.substitution)
+                        })
+                    }
                     // It always has an parameter for Future::Output type.
                     ImplTraitId::AsyncBlockTypeImplTrait(..) => unreachable!(),
                 };
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
index 98384c47490..d1ffd5046c3 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
@@ -2825,3 +2825,30 @@ fn unsized_local() {
         |e| matches!(e, ConstEvalError::MirLowerError(MirLowerError::UnsizedTemporary(_))),
     );
 }
+
+#[test]
+fn recursive_adt() {
+    check_fail(
+        r#"
+        //- minicore: coerce_unsized, index, slice
+        pub enum TagTree {
+            Leaf,
+            Choice(&'static [TagTree]),
+        }
+        const GOAL: TagTree = {
+            const TAG_TREE: TagTree = TagTree::Choice(&[
+                {
+                    const VARIANT_TAG_TREE: TagTree = TagTree::Choice(
+                        &[
+                            TagTree::Leaf,
+                        ],
+                    );
+                    VARIANT_TAG_TREE
+                },
+            ]);
+            TAG_TREE
+        };
+    "#,
+        |e| matches!(e, ConstEvalError::MirEvalError(MirEvalError::StackOverflow)),
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
index 28c497989fe..90bf46b5056 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
@@ -11,7 +11,7 @@ use base_db::{
 use hir_def::{
     db::DefDatabase, hir::ExprId, layout::TargetDataLayout, AdtId, BlockId, ConstParamId,
     DefWithBodyId, EnumVariantId, FunctionId, GeneralConstId, GenericDefId, ImplId,
-    LifetimeParamId, LocalFieldId, StaticId, TypeOrConstParamId, VariantId,
+    LifetimeParamId, LocalFieldId, StaticId, TypeAliasId, TypeOrConstParamId, VariantId,
 };
 use la_arena::ArenaMap;
 use smallvec::SmallVec;
@@ -23,9 +23,9 @@ use crate::{
     layout::{Layout, LayoutError},
     method_resolution::{InherentImpls, TraitImpls, TyFingerprint},
     mir::{BorrowckResult, MirBody, MirLowerError},
-    Binders, CallableDefId, ClosureId, Const, FnDefId, GenericArg, ImplTraitId, InferenceResult,
-    Interner, PolyFnSig, QuantifiedWhereClause, ReturnTypeImplTraits, Substitution,
-    TraitEnvironment, TraitRef, Ty, TyDefId, ValueTyDefId,
+    Binders, CallableDefId, ClosureId, Const, FnDefId, GenericArg, ImplTraitId, ImplTraits,
+    InferenceResult, Interner, PolyFnSig, QuantifiedWhereClause, Substitution, TraitEnvironment,
+    TraitRef, Ty, TyDefId, ValueTyDefId,
 };
 use hir_expand::name::Name;
 
@@ -132,10 +132,10 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
     fn callable_item_signature(&self, def: CallableDefId) -> PolyFnSig;
 
     #[salsa::invoke(crate::lower::return_type_impl_traits)]
-    fn return_type_impl_traits(
-        &self,
-        def: FunctionId,
-    ) -> Option<Arc<Binders<ReturnTypeImplTraits>>>;
+    fn return_type_impl_traits(&self, def: FunctionId) -> Option<Arc<Binders<ImplTraits>>>;
+
+    #[salsa::invoke(crate::lower::type_alias_impl_traits)]
+    fn type_alias_impl_traits(&self, def: TypeAliasId) -> Option<Arc<Binders<ImplTraits>>>;
 
     #[salsa::invoke(crate::lower::generic_predicates_for_param_query)]
     #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)]
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
index 67cfbc294df..20b0da441da 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
@@ -11,7 +11,6 @@ use hir_def::{ItemContainerId, Lookup};
 use hir_expand::name;
 use itertools::Itertools;
 use rustc_hash::FxHashSet;
-use rustc_pattern_analysis::usefulness::{compute_match_usefulness, ValidityConstraint};
 use syntax::{ast, AstNode};
 use tracing::debug;
 use triomphe::Arc;
@@ -234,13 +233,7 @@ impl ExprValidator {
             return;
         }
 
-        let report = match compute_match_usefulness(
-            &cx,
-            m_arms.as_slice(),
-            scrut_ty.clone(),
-            ValidityConstraint::ValidOnly,
-            None,
-        ) {
+        let report = match cx.compute_match_usefulness(m_arms.as_slice(), scrut_ty.clone()) {
             Ok(report) => report,
             Err(()) => return,
         };
@@ -282,13 +275,7 @@ impl ExprValidator {
                 continue;
             }
 
-            let report = match compute_match_usefulness(
-                &cx,
-                &[match_arm],
-                ty.clone(),
-                ValidityConstraint::ValidOnly,
-                None,
-            ) {
+            let report = match cx.compute_match_usefulness(&[match_arm], ty.clone()) {
                 Ok(v) => v,
                 Err(e) => {
                     debug!(?e, "match usefulness error");
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
index ca058428796..f45beb4c92b 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
@@ -8,7 +8,8 @@ use rustc_hash::FxHashMap;
 use rustc_pattern_analysis::{
     constructor::{Constructor, ConstructorSet, VariantVisibility},
     index::IdxContainer,
-    Captures, PrivateUninhabitedField, TypeCx,
+    usefulness::{compute_match_usefulness, PlaceValidity, UsefulnessReport},
+    Captures, PatCx, PrivateUninhabitedField,
 };
 use smallvec::{smallvec, SmallVec};
 use stdx::never;
@@ -59,6 +60,18 @@ impl<'p> MatchCheckCtx<'p> {
         Self { module, body, db, exhaustive_patterns, min_exhaustive_patterns }
     }
 
+    pub(crate) fn compute_match_usefulness(
+        &self,
+        arms: &[MatchArm<'p>],
+        scrut_ty: Ty,
+    ) -> Result<UsefulnessReport<'p, Self>, ()> {
+        // FIXME: Determine place validity correctly. For now, err on the safe side.
+        let place_validity = PlaceValidity::MaybeInvalid;
+        // Measured to take ~100ms on modern hardware.
+        let complexity_limit = Some(500000);
+        compute_match_usefulness(self, arms, scrut_ty, place_validity, complexity_limit)
+    }
+
     fn is_uninhabited(&self, ty: &Ty) -> bool {
         is_ty_uninhabited_from(ty, self.module, self.db)
     }
@@ -107,15 +120,17 @@ impl<'p> MatchCheckCtx<'p> {
     }
 
     pub(crate) fn lower_pat(&self, pat: &Pat) -> DeconstructedPat<'p> {
-        let singleton = |pat| vec![pat];
+        let singleton = |pat: DeconstructedPat<'p>| vec![pat.at_index(0)];
         let ctor;
-        let fields: Vec<_>;
+        let mut fields: Vec<_>;
+        let arity;
 
         match pat.kind.as_ref() {
             PatKind::Binding { subpattern: Some(subpat), .. } => return self.lower_pat(subpat),
             PatKind::Binding { subpattern: None, .. } | PatKind::Wild => {
                 ctor = Wildcard;
                 fields = Vec::new();
+                arity = 0;
             }
             PatKind::Deref { subpattern } => {
                 ctor = match pat.ty.kind(Interner) {
@@ -128,23 +143,22 @@ impl<'p> MatchCheckCtx<'p> {
                     }
                 };
                 fields = singleton(self.lower_pat(subpattern));
+                arity = 1;
             }
             PatKind::Leaf { subpatterns } | PatKind::Variant { subpatterns, .. } => {
+                fields = subpatterns
+                    .iter()
+                    .map(|pat| {
+                        let idx: u32 = pat.field.into_raw().into();
+                        self.lower_pat(&pat.pattern).at_index(idx as usize)
+                    })
+                    .collect();
                 match pat.ty.kind(Interner) {
                     TyKind::Tuple(_, substs) => {
                         ctor = Struct;
-                        let mut wilds: Vec<_> = substs
-                            .iter(Interner)
-                            .map(|arg| arg.assert_ty_ref(Interner).clone())
-                            .map(DeconstructedPat::wildcard)
-                            .collect();
-                        for pat in subpatterns {
-                            let idx: u32 = pat.field.into_raw().into();
-                            wilds[idx as usize] = self.lower_pat(&pat.pattern);
-                        }
-                        fields = wilds
+                        arity = substs.len(Interner);
                     }
-                    TyKind::Adt(adt, substs) if is_box(self.db, adt.0) => {
+                    TyKind::Adt(adt, _) if is_box(self.db, adt.0) => {
                         // The only legal patterns of type `Box` (outside `std`) are `_` and box
                         // patterns. If we're here we can assume this is a box pattern.
                         // FIXME(Nadrieril): A `Box` can in theory be matched either with `Box(_,
@@ -157,16 +171,9 @@ impl<'p> MatchCheckCtx<'p> {
                         // normally or through box-patterns. We'll have to figure out a proper
                         // solution when we introduce generalized deref patterns. Also need to
                         // prevent mixing of those two options.
-                        let pat =
-                            subpatterns.iter().find(|pat| pat.field.into_raw() == 0u32.into());
-                        let field = if let Some(pat) = pat {
-                            self.lower_pat(&pat.pattern)
-                        } else {
-                            let ty = substs.at(Interner, 0).assert_ty_ref(Interner).clone();
-                            DeconstructedPat::wildcard(ty)
-                        };
+                        fields.retain(|ipat| ipat.idx == 0);
                         ctor = Struct;
-                        fields = singleton(field);
+                        arity = 1;
                     }
                     &TyKind::Adt(adt, _) => {
                         ctor = match pat.kind.as_ref() {
@@ -181,37 +188,33 @@ impl<'p> MatchCheckCtx<'p> {
                             }
                         };
                         let variant = Self::variant_id_for_adt(&ctor, adt.0).unwrap();
-                        // Fill a vec with wildcards, then place the fields we have at the right
-                        // index.
-                        let mut wilds: Vec<_> = self
-                            .list_variant_fields(&pat.ty, variant)
-                            .map(|(_, ty)| ty)
-                            .map(DeconstructedPat::wildcard)
-                            .collect();
-                        for pat in subpatterns {
-                            let field_id: u32 = pat.field.into_raw().into();
-                            wilds[field_id as usize] = self.lower_pat(&pat.pattern);
-                        }
-                        fields = wilds;
+                        arity = variant.variant_data(self.db.upcast()).fields().len();
                     }
                     _ => {
                         never!("pattern has unexpected type: pat: {:?}, ty: {:?}", pat, &pat.ty);
                         ctor = Wildcard;
-                        fields = Vec::new();
+                        fields.clear();
+                        arity = 0;
                     }
                 }
             }
             &PatKind::LiteralBool { value } => {
                 ctor = Bool(value);
                 fields = Vec::new();
+                arity = 0;
             }
             PatKind::Or { pats } => {
                 ctor = Or;
-                fields = pats.iter().map(|pat| self.lower_pat(pat)).collect();
+                fields = pats
+                    .iter()
+                    .enumerate()
+                    .map(|(i, pat)| self.lower_pat(pat).at_index(i))
+                    .collect();
+                arity = pats.len();
             }
         }
         let data = PatData { db: self.db };
-        DeconstructedPat::new(ctor, fields, pat.ty.clone(), data)
+        DeconstructedPat::new(ctor, fields, arity, pat.ty.clone(), data)
     }
 
     pub(crate) fn hoist_witness_pat(&self, pat: &WitnessPat<'p>) -> Pat {
@@ -271,7 +274,7 @@ impl<'p> MatchCheckCtx<'p> {
     }
 }
 
-impl<'p> TypeCx for MatchCheckCtx<'p> {
+impl<'p> PatCx for MatchCheckCtx<'p> {
     type Error = ();
     type Ty = Ty;
     type VariantIdx = EnumVariantId;
@@ -453,7 +456,7 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
         let variant =
             pat.ty().as_adt().and_then(|(adt, _)| Self::variant_id_for_adt(pat.ctor(), adt));
 
-        let db = pat.data().unwrap().db;
+        let db = pat.data().db;
         if let Some(variant) = variant {
             match variant {
                 VariantId::EnumVariantId(v) => {
@@ -475,7 +478,6 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
     }
 
     fn complexity_exceeded(&self) -> Result<(), Self::Error> {
-        // FIXME(Nadrieril): make use of the complexity counter.
         Err(())
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
index 20964f5acbd..8740ae6797c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -938,18 +938,32 @@ impl HirDisplay for Ty {
                 f.end_location_link();
                 if parameters.len(Interner) > 0 {
                     let generics = generics(db.upcast(), def.into());
-                    let (parent_params, self_param, type_params, const_params, _impl_trait_params) =
-                        generics.provenance_split();
-                    let total_len = parent_params + self_param + type_params + const_params;
+                    let (
+                        parent_params,
+                        self_param,
+                        type_params,
+                        const_params,
+                        _impl_trait_params,
+                        lifetime_params,
+                    ) = generics.provenance_split();
+                    let total_len =
+                        parent_params + self_param + type_params + const_params + lifetime_params;
                     // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
                     if total_len > 0 {
-                        // `parameters` are in the order of fn's params (including impl traits),
+                        // `parameters` are in the order of fn's params (including impl traits), fn's lifetimes
                         // parent's params (those from enclosing impl or trait, if any).
                         let parameters = parameters.as_slice(Interner);
                         let fn_params_len = self_param + type_params + const_params;
+                        // This will give slice till last type or const
                         let fn_params = parameters.get(..fn_params_len);
+                        let fn_lt_params =
+                            parameters.get(fn_params_len..(fn_params_len + lifetime_params));
                         let parent_params = parameters.get(parameters.len() - parent_params..);
-                        let params = parent_params.into_iter().chain(fn_params).flatten();
+                        let params = parent_params
+                            .into_iter()
+                            .chain(fn_lt_params)
+                            .chain(fn_params)
+                            .flatten();
                         write!(f, "<")?;
                         f.write_joined(params, ", ")?;
                         write!(f, ">")?;
@@ -1063,6 +1077,20 @@ impl HirDisplay for Ty {
                         )?;
                         // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
                     }
+                    ImplTraitId::AssociatedTypeImplTrait(alias, idx) => {
+                        let datas =
+                            db.type_alias_impl_traits(alias).expect("impl trait id without data");
+                        let data =
+                            (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
+                        let bounds = data.substitute(Interner, &parameters);
+                        let krate = alias.krate(db.upcast());
+                        write_bounds_like_dyn_trait_with_prefix(
+                            f,
+                            "impl",
+                            bounds.skip_binders(),
+                            SizedByDefault::Sized { anchor: krate },
+                        )?;
+                    }
                     ImplTraitId::AsyncBlockTypeImplTrait(body, ..) => {
                         let future_trait = db
                             .lang_item(body.module(db.upcast()).krate(), LangItem::Future)
@@ -1228,6 +1256,20 @@ impl HirDisplay for Ty {
                             SizedByDefault::Sized { anchor: krate },
                         )?;
                     }
+                    ImplTraitId::AssociatedTypeImplTrait(alias, idx) => {
+                        let datas =
+                            db.type_alias_impl_traits(alias).expect("impl trait id without data");
+                        let data =
+                            (*datas).as_ref().map(|rpit| rpit.impl_traits[idx].bounds.clone());
+                        let bounds = data.substitute(Interner, &opaque_ty.substitution);
+                        let krate = alias.krate(db.upcast());
+                        write_bounds_like_dyn_trait_with_prefix(
+                            f,
+                            "impl",
+                            bounds.skip_binders(),
+                            SizedByDefault::Sized { anchor: krate },
+                        )?;
+                    }
                     ImplTraitId::AsyncBlockTypeImplTrait(..) => {
                         write!(f, "{{async block}}")?;
                     }
@@ -1280,8 +1322,17 @@ fn hir_fmt_generics(
     generic_def: Option<hir_def::GenericDefId>,
 ) -> Result<(), HirDisplayError> {
     let db = f.db;
-    let lifetime_args_count = generic_def.map_or(0, |g| db.generic_params(g).lifetimes.len());
-    if parameters.len(Interner) + lifetime_args_count > 0 {
+    if parameters.len(Interner) > 0 {
+        use std::cmp::Ordering;
+        let param_compare =
+            |a: &GenericArg, b: &GenericArg| match (a.data(Interner), b.data(Interner)) {
+                (crate::GenericArgData::Lifetime(_), crate::GenericArgData::Lifetime(_)) => {
+                    Ordering::Equal
+                }
+                (crate::GenericArgData::Lifetime(_), _) => Ordering::Less,
+                (_, crate::GenericArgData::Lifetime(_)) => Ordering::Less,
+                (_, _) => Ordering::Equal,
+            };
         let parameters_to_write = if f.display_target.is_source_code() || f.omit_verbose_types() {
             match generic_def
                 .map(|generic_def_id| db.generic_defaults(generic_def_id))
@@ -1307,6 +1358,11 @@ fn hir_fmt_generics(
                                 return true;
                             }
                         }
+                        if parameter.lifetime(Interner).map(|it| it.data(Interner))
+                            == Some(&crate::LifetimeData::Static)
+                        {
+                            return true;
+                        }
                         let default_parameter = match default_parameters.get(i) {
                             Some(it) => it,
                             None => return true,
@@ -1327,16 +1383,12 @@ fn hir_fmt_generics(
         } else {
             parameters.as_slice(Interner)
         };
-        if !parameters_to_write.is_empty() || lifetime_args_count != 0 {
+        //FIXME: Should handle the ordering of lifetimes when creating substitutions
+        let mut parameters_to_write = parameters_to_write.to_vec();
+        parameters_to_write.sort_by(param_compare);
+        if !parameters_to_write.is_empty() {
             write!(f, "<")?;
             let mut first = true;
-            for _ in 0..lifetime_args_count {
-                if !first {
-                    write!(f, ", ")?;
-                }
-                first = false;
-                write!(f, "'_")?;
-            }
             for generic_arg in parameters_to_write {
                 if !first {
                     write!(f, ", ")?;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
index 34ba17f145e..be3b50e1411 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
@@ -25,8 +25,11 @@ pub(crate) mod unify;
 use std::{convert::identity, iter, ops::Index};
 
 use chalk_ir::{
-    cast::Cast, fold::TypeFoldable, interner::HasInterner, DebruijnIndex, Mutability, Safety,
-    Scalar, TyKind, TypeFlags, Variance,
+    cast::Cast,
+    fold::TypeFoldable,
+    interner::HasInterner,
+    visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor},
+    DebruijnIndex, Mutability, Safety, Scalar, TyKind, TypeFlags, Variance,
 };
 use either::Either;
 use hir_def::{
@@ -39,7 +42,7 @@ use hir_def::{
     layout::Integer,
     path::{ModPath, Path},
     resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
-    type_ref::TypeRef,
+    type_ref::{LifetimeRef, TypeRef},
     AdtId, AssocItemId, DefWithBodyId, FieldId, FunctionId, ItemContainerId, Lookup, TraitId,
     TupleFieldId, TupleId, TypeAliasId, VariantId,
 };
@@ -53,14 +56,14 @@ use triomphe::Arc;
 use crate::{
     db::HirDatabase,
     fold_tys,
-    infer::coerce::CoerceMany,
+    infer::{coerce::CoerceMany, unify::InferenceTable},
     lower::ImplTraitLoweringMode,
     static_lifetime, to_assoc_type_id,
     traits::FnTrait,
     utils::{InTypeConstIdMetadata, UnevaluatedConstEvaluatorFolder},
     AliasEq, AliasTy, Binders, ClosureId, Const, DomainGoal, GenericArg, Goal, ImplTraitId,
-    InEnvironment, Interner, Lifetime, ProjectionTy, RpitId, Substitution, TraitEnvironment,
-    TraitRef, Ty, TyBuilder, TyExt,
+    ImplTraitIdx, InEnvironment, Interner, Lifetime, OpaqueTyId, ProjectionTy, Substitution,
+    TraitEnvironment, Ty, TyBuilder, TyExt,
 };
 
 // This lint has a false positive here. See the link below for details.
@@ -422,7 +425,7 @@ pub struct InferenceResult {
     /// unresolved or missing subpatterns or subpatterns of mismatched types.
     pub type_of_pat: ArenaMap<PatId, Ty>,
     pub type_of_binding: ArenaMap<BindingId, Ty>,
-    pub type_of_rpit: ArenaMap<RpitId, Ty>,
+    pub type_of_rpit: ArenaMap<ImplTraitIdx, Ty>,
     /// Type of the result of `.into_iter()` on the for. `ExprId` is the one of the whole for loop.
     pub type_of_for_iterator: FxHashMap<ExprId, Ty>,
     type_mismatches: FxHashMap<ExprOrPatId, TypeMismatch>,
@@ -752,7 +755,12 @@ impl<'a> InferenceContext<'a> {
     }
 
     fn collect_const(&mut self, data: &ConstData) {
-        self.return_ty = self.make_ty(&data.type_ref);
+        let return_ty = self.make_ty(&data.type_ref);
+
+        // Constants might be associated items that define ATPITs.
+        self.insert_atpit_coercion_table(iter::once(&return_ty));
+
+        self.return_ty = return_ty;
     }
 
     fn collect_static(&mut self, data: &StaticData) {
@@ -785,11 +793,13 @@ impl<'a> InferenceContext<'a> {
                 self.write_binding_ty(self_param, ty);
             }
         }
+        let mut params_and_ret_tys = Vec::new();
         for (ty, pat) in param_tys.zip(&*self.body.params) {
             let ty = self.insert_type_vars(ty);
             let ty = self.normalize_associated_types_in(ty);
 
             self.infer_top_pat(*pat, &ty);
+            params_and_ret_tys.push(ty);
         }
         let return_ty = &*data.ret_type;
 
@@ -801,8 +811,11 @@ impl<'a> InferenceContext<'a> {
         let return_ty = if let Some(rpits) = self.db.return_type_impl_traits(func) {
             // RPIT opaque types use substitution of their parent function.
             let fn_placeholders = TyBuilder::placeholder_subst(self.db, func);
-            let result =
-                self.insert_inference_vars_for_rpit(return_ty, rpits.clone(), fn_placeholders);
+            let result = self.insert_inference_vars_for_impl_trait(
+                return_ty,
+                rpits.clone(),
+                fn_placeholders,
+            );
             let rpits = rpits.skip_binders();
             for (id, _) in rpits.impl_traits.iter() {
                 if let Entry::Vacant(e) = self.result.type_of_rpit.entry(id) {
@@ -817,13 +830,19 @@ impl<'a> InferenceContext<'a> {
 
         self.return_ty = self.normalize_associated_types_in(return_ty);
         self.return_coercion = Some(CoerceMany::new(self.return_ty.clone()));
+
+        // Functions might be associated items that define ATPITs.
+        // To define an ATPITs, that ATPIT must appear in the function's signatures.
+        // So, it suffices to check for params and return types.
+        params_and_ret_tys.push(self.return_ty.clone());
+        self.insert_atpit_coercion_table(params_and_ret_tys.iter());
     }
 
-    fn insert_inference_vars_for_rpit<T>(
+    fn insert_inference_vars_for_impl_trait<T>(
         &mut self,
         t: T,
-        rpits: Arc<chalk_ir::Binders<crate::ReturnTypeImplTraits>>,
-        fn_placeholders: Substitution,
+        rpits: Arc<chalk_ir::Binders<crate::ImplTraits>>,
+        placeholders: Substitution,
     ) -> T
     where
         T: crate::HasInterner<Interner = Interner> + crate::TypeFoldable<Interner>,
@@ -837,6 +856,7 @@ impl<'a> InferenceContext<'a> {
                 };
                 let idx = match self.db.lookup_intern_impl_trait_id(opaque_ty_id.into()) {
                     ImplTraitId::ReturnTypeImplTrait(_, idx) => idx,
+                    ImplTraitId::AssociatedTypeImplTrait(_, idx) => idx,
                     _ => unreachable!(),
                 };
                 let bounds =
@@ -844,15 +864,14 @@ impl<'a> InferenceContext<'a> {
                 let var = self.table.new_type_var();
                 let var_subst = Substitution::from1(Interner, var.clone());
                 for bound in bounds {
-                    let predicate =
-                        bound.map(|it| it.cloned()).substitute(Interner, &fn_placeholders);
+                    let predicate = bound.map(|it| it.cloned()).substitute(Interner, &placeholders);
                     let (var_predicate, binders) =
                         predicate.substitute(Interner, &var_subst).into_value_and_skipped_binders();
                     always!(binders.is_empty(Interner)); // quantified where clauses not yet handled
-                    let var_predicate = self.insert_inference_vars_for_rpit(
+                    let var_predicate = self.insert_inference_vars_for_impl_trait(
                         var_predicate,
                         rpits.clone(),
-                        fn_placeholders.clone(),
+                        placeholders.clone(),
                     );
                     self.push_obligation(var_predicate.cast(Interner));
                 }
@@ -863,6 +882,106 @@ impl<'a> InferenceContext<'a> {
         )
     }
 
+    /// The coercion of a non-inference var into an opaque type should fail,
+    /// but not in the defining sites of the ATPITs.
+    /// In such cases, we insert an proxy inference var for each ATPIT,
+    /// and coerce into it instead of ATPIT itself.
+    ///
+    /// The inference var stretagy is effective because;
+    ///
+    /// - It can still unify types that coerced into ATPIT
+    /// - We are pushing `impl Trait` bounds into it
+    ///
+    /// This function inserts a map that maps the opaque type to that proxy inference var.
+    fn insert_atpit_coercion_table<'b>(&mut self, tys: impl Iterator<Item = &'b Ty>) {
+        struct OpaqueTyCollector<'a, 'b> {
+            table: &'b mut InferenceTable<'a>,
+            opaque_tys: FxHashMap<OpaqueTyId, Ty>,
+        }
+
+        impl<'a, 'b> TypeVisitor<Interner> for OpaqueTyCollector<'a, 'b> {
+            type BreakTy = ();
+
+            fn as_dyn(&mut self) -> &mut dyn TypeVisitor<Interner, BreakTy = Self::BreakTy> {
+                self
+            }
+
+            fn interner(&self) -> Interner {
+                Interner
+            }
+
+            fn visit_ty(
+                &mut self,
+                ty: &chalk_ir::Ty<Interner>,
+                outer_binder: DebruijnIndex,
+            ) -> std::ops::ControlFlow<Self::BreakTy> {
+                let ty = self.table.resolve_ty_shallow(ty);
+
+                if let TyKind::OpaqueType(id, _) = ty.kind(Interner) {
+                    self.opaque_tys.insert(*id, ty.clone());
+                }
+
+                ty.super_visit_with(self, outer_binder)
+            }
+        }
+
+        // Early return if this is not happening inside the impl block
+        let impl_id = if let Some(impl_id) = self.resolver.impl_def() {
+            impl_id
+        } else {
+            return;
+        };
+
+        let assoc_tys: FxHashSet<_> = self
+            .db
+            .impl_data(impl_id)
+            .items
+            .iter()
+            .filter_map(|item| match item {
+                AssocItemId::TypeAliasId(alias) => Some(*alias),
+                _ => None,
+            })
+            .collect();
+        if assoc_tys.is_empty() {
+            return;
+        }
+
+        let mut collector =
+            OpaqueTyCollector { table: &mut self.table, opaque_tys: FxHashMap::default() };
+        for ty in tys {
+            ty.visit_with(collector.as_dyn(), DebruijnIndex::INNERMOST);
+        }
+        let atpit_coercion_table: FxHashMap<_, _> = collector
+            .opaque_tys
+            .into_iter()
+            .filter_map(|(opaque_ty_id, ty)| {
+                if let ImplTraitId::AssociatedTypeImplTrait(alias_id, _) =
+                    self.db.lookup_intern_impl_trait_id(opaque_ty_id.into())
+                {
+                    if assoc_tys.contains(&alias_id) {
+                        let atpits = self
+                            .db
+                            .type_alias_impl_traits(alias_id)
+                            .expect("Marked as ATPIT but no impl traits!");
+                        let alias_placeholders = TyBuilder::placeholder_subst(self.db, alias_id);
+                        let ty = self.insert_inference_vars_for_impl_trait(
+                            ty,
+                            atpits,
+                            alias_placeholders,
+                        );
+                        return Some((opaque_ty_id, ty));
+                    }
+                }
+
+                None
+            })
+            .collect();
+
+        if !atpit_coercion_table.is_empty() {
+            self.table.atpit_coercion_table = Some(atpit_coercion_table);
+        }
+    }
+
     fn infer_body(&mut self) {
         match self.return_coercion {
             Some(_) => self.infer_return(self.body.body_expr),
@@ -918,6 +1037,12 @@ impl<'a> InferenceContext<'a> {
         self.result.standard_types.unknown.clone()
     }
 
+    fn make_lifetime(&mut self, lifetime_ref: &LifetimeRef) -> Lifetime {
+        let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, self.owner.into());
+        let lt = ctx.lower_lifetime(lifetime_ref);
+        self.insert_type_vars(lt)
+    }
+
     /// Replaces `Ty::Error` by a new type var, so we can maybe still infer it.
     fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
         self.table.insert_type_vars_shallow(ty)
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs
index ff6de61ba64..cfbbc9dd6c0 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs
@@ -276,6 +276,23 @@ impl InferenceTable<'_> {
             return success(simple(Adjust::NeverToAny)(to_ty.clone()), to_ty.clone(), vec![]);
         }
 
+        // If we are coercing into an ATPIT, coerce into its proxy inference var, instead.
+        let mut to_ty = to_ty;
+        let _to;
+        if let Some(atpit_table) = &self.atpit_coercion_table {
+            if let TyKind::OpaqueType(opaque_ty_id, _) = to_ty.kind(Interner) {
+                if !matches!(
+                    from_ty.kind(Interner),
+                    TyKind::InferenceVar(..) | TyKind::OpaqueType(..)
+                ) {
+                    if let Some(ty) = atpit_table.get(opaque_ty_id) {
+                        _to = ty.clone();
+                        to_ty = &_to;
+                    }
+                }
+            }
+        }
+
         // Consider coercing the subtype to a DST
         if let Ok(ret) = self.try_coerce_unsized(&from_ty, to_ty) {
             return Ok(ret);
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
index a3dab1fd9d5..35d59679355 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
@@ -8,13 +8,12 @@ use std::{
 use chalk_ir::{cast::Cast, fold::Shift, DebruijnIndex, Mutability, TyVariableKind};
 use either::Either;
 use hir_def::{
-    generics::TypeOrConstParamData,
     hir::{
         ArithOp, Array, BinaryOp, ClosureKind, Expr, ExprId, LabelId, Literal, Statement, UnaryOp,
     },
     lang_item::{LangItem, LangItemTarget},
-    path::{GenericArg, GenericArgs, Path},
-    BlockId, ConstParamId, FieldId, ItemContainerId, Lookup, TupleFieldId, TupleId,
+    path::{GenericArgs, Path},
+    BlockId, FieldId, GenericParamId, ItemContainerId, Lookup, TupleFieldId, TupleId,
 };
 use hir_expand::name::{name, Name};
 use stdx::always;
@@ -1816,10 +1815,17 @@ impl InferenceContext<'_> {
         def_generics: Generics,
         generic_args: Option<&GenericArgs>,
     ) -> Substitution {
-        let (parent_params, self_params, type_params, const_params, impl_trait_params) =
-            def_generics.provenance_split();
+        let (
+            parent_params,
+            self_params,
+            type_params,
+            const_params,
+            impl_trait_params,
+            lifetime_params,
+        ) = def_generics.provenance_split();
         assert_eq!(self_params, 0); // method shouldn't have another Self param
-        let total_len = parent_params + type_params + const_params + impl_trait_params;
+        let total_len =
+            parent_params + type_params + const_params + impl_trait_params + lifetime_params;
         let mut substs = Vec::with_capacity(total_len);
 
         // handle provided arguments
@@ -1828,8 +1834,7 @@ impl InferenceContext<'_> {
             for (arg, kind_id) in generic_args
                 .args
                 .iter()
-                .filter(|arg| !matches!(arg, GenericArg::Lifetime(_)))
-                .take(type_params + const_params)
+                .take(type_params + const_params + lifetime_params)
                 .zip(def_generics.iter_id())
             {
                 if let Some(g) = generic_arg_to_chalk(
@@ -1850,6 +1855,7 @@ impl InferenceContext<'_> {
                             DebruijnIndex::INNERMOST,
                         )
                     },
+                    |this, lt_ref| this.make_lifetime(lt_ref),
                 ) {
                     substs.push(g);
                 }
@@ -1858,16 +1864,17 @@ impl InferenceContext<'_> {
 
         // Handle everything else as unknown. This also handles generic arguments for the method's
         // parent (impl or trait), which should come after those for the method.
-        for (id, data) in def_generics.iter().skip(substs.len()) {
-            match data {
-                TypeOrConstParamData::TypeParamData(_) => {
+        for (id, _data) in def_generics.iter().skip(substs.len()) {
+            match id {
+                GenericParamId::TypeParamId(_) => {
                     substs.push(self.table.new_type_var().cast(Interner))
                 }
-                TypeOrConstParamData::ConstParamData(_) => substs.push(
-                    self.table
-                        .new_const_var(self.db.const_param_ty(ConstParamId::from_unchecked(id)))
-                        .cast(Interner),
-                ),
+                GenericParamId::ConstParamId(id) => {
+                    substs.push(self.table.new_const_var(self.db.const_param_ty(id)).cast(Interner))
+                }
+                GenericParamId::LifetimeParamId(_) => {
+                    substs.push(self.table.new_lifetime_var().cast(Interner))
+                }
             }
         }
         assert_eq!(substs.len(), total_len);
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
index 8f537bb448b..9a1835b625b 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
@@ -11,15 +11,15 @@ use stdx::never;
 
 use crate::{
     builder::ParamKind,
-    consteval,
+    consteval, error_lifetime,
     method_resolution::{self, VisibleFromModule},
     to_chalk_trait_id,
     utils::generics,
-    InferenceDiagnostic, Interner, Substitution, TraitRefExt, Ty, TyBuilder, TyExt, TyKind,
-    ValueTyDefId,
+    InferenceDiagnostic, Interner, Substitution, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt,
+    TyKind, ValueTyDefId,
 };
 
-use super::{ExprOrPatId, InferenceContext, TraitRef};
+use super::{ExprOrPatId, InferenceContext};
 
 impl InferenceContext<'_> {
     pub(super) fn infer_path(&mut self, path: &Path, id: ExprOrPatId) -> Option<Ty> {
@@ -111,6 +111,7 @@ impl InferenceContext<'_> {
                 it.next().unwrap_or_else(|| match x {
                     ParamKind::Type => self.result.standard_types.unknown.clone().cast(Interner),
                     ParamKind::Const(ty) => consteval::unknown_const_as_generic(ty.clone()),
+                    ParamKind::Lifetime => error_lifetime().cast(Interner),
                 })
             })
             .build();
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
index be7547f9bae..afb89fe1e5b 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
@@ -10,16 +10,18 @@ use chalk_solve::infer::ParameterEnaVariableExt;
 use either::Either;
 use ena::unify::UnifyKey;
 use hir_expand::name;
+use rustc_hash::FxHashMap;
 use smallvec::SmallVec;
 use triomphe::Arc;
 
 use super::{InferOk, InferResult, InferenceContext, TypeError};
 use crate::{
-    consteval::unknown_const, db::HirDatabase, fold_tys_and_consts, static_lifetime,
-    to_chalk_trait_id, traits::FnTrait, AliasEq, AliasTy, BoundVar, Canonical, Const, ConstValue,
-    DebruijnIndex, DomainGoal, GenericArg, GenericArgData, Goal, GoalData, Guidance, InEnvironment,
-    InferenceVar, Interner, Lifetime, ParamKind, ProjectionTy, ProjectionTyExt, Scalar, Solution,
-    Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind, VariableKind, WhereClause,
+    consteval::unknown_const, db::HirDatabase, fold_generic_args, fold_tys_and_consts,
+    static_lifetime, to_chalk_trait_id, traits::FnTrait, AliasEq, AliasTy, BoundVar, Canonical,
+    Const, ConstValue, DebruijnIndex, DomainGoal, GenericArg, GenericArgData, Goal, GoalData,
+    Guidance, InEnvironment, InferenceVar, Interner, Lifetime, OpaqueTyId, ParamKind, ProjectionTy,
+    ProjectionTyExt, Scalar, Solution, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt,
+    TyKind, VariableKind, WhereClause,
 };
 
 impl InferenceContext<'_> {
@@ -239,6 +241,7 @@ type ChalkInferenceTable = chalk_solve::infer::InferenceTable<Interner>;
 pub(crate) struct InferenceTable<'a> {
     pub(crate) db: &'a dyn HirDatabase,
     pub(crate) trait_env: Arc<TraitEnvironment>,
+    pub(crate) atpit_coercion_table: Option<FxHashMap<OpaqueTyId, Ty>>,
     var_unification_table: ChalkInferenceTable,
     type_variable_table: SmallVec<[TypeVariableFlags; 16]>,
     pending_obligations: Vec<Canonicalized<InEnvironment<Goal>>>,
@@ -258,6 +261,7 @@ impl<'a> InferenceTable<'a> {
         InferenceTable {
             db,
             trait_env,
+            atpit_coercion_table: None,
             var_unification_table: ChalkInferenceTable::new(),
             type_variable_table: SmallVec::new(),
             pending_obligations: Vec::new(),
@@ -803,6 +807,7 @@ impl<'a> InferenceTable<'a> {
             .fill(|it| {
                 let arg = match it {
                     ParamKind::Type => self.new_type_var(),
+                    ParamKind::Lifetime => unreachable!("Tuple with lifetime parameter"),
                     ParamKind::Const(_) => unreachable!("Tuple with const parameter"),
                 };
                 arg_tys.push(arg.clone());
@@ -857,11 +862,16 @@ impl<'a> InferenceTable<'a> {
     where
         T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
     {
-        fold_tys_and_consts(
+        fold_generic_args(
             ty,
-            |it, _| match it {
-                Either::Left(ty) => Either::Left(self.insert_type_vars_shallow(ty)),
-                Either::Right(c) => Either::Right(self.insert_const_vars_shallow(c)),
+            |arg, _| match arg {
+                GenericArgData::Ty(ty) => GenericArgData::Ty(self.insert_type_vars_shallow(ty)),
+                // FIXME: insert lifetime vars once LifetimeData::InferenceVar
+                // and specific error variant for lifetimes start being constructed
+                GenericArgData::Lifetime(lt) => GenericArgData::Lifetime(lt),
+                GenericArgData::Const(c) => {
+                    GenericArgData::Const(self.insert_const_vars_shallow(c))
+                }
             },
             DebruijnIndex::INNERMOST,
         )
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
index 9655981cc9c..dd949e26c2a 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
@@ -389,6 +389,9 @@ pub fn layout_of_ty_query(
                     let infer = db.infer(func.into());
                     return db.layout_of_ty(infer.type_of_rpit[idx].clone(), trait_env);
                 }
+                crate::ImplTraitId::AssociatedTypeImplTrait(..) => {
+                    return Err(LayoutError::NotImplemented);
+                }
                 crate::ImplTraitId::AsyncBlockTypeImplTrait(_, _) => {
                     return Err(LayoutError::NotImplemented)
                 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
index ec97bdc2c43..ba64f5c8d7e 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
@@ -15,7 +15,8 @@ extern crate rustc_abi;
 #[cfg(not(feature = "in-rust-tree"))]
 extern crate ra_ap_rustc_abi as rustc_abi;
 
-// No need to use the in-tree one.
+// Use the crates.io version unconditionally until the API settles enough that we can switch to
+// using the in-tree one.
 extern crate ra_ap_rustc_pattern_analysis as rustc_pattern_analysis;
 
 mod builder;
@@ -89,8 +90,8 @@ pub use lower::{
 };
 pub use mapping::{
     from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx,
-    lt_from_placeholder_idx, to_assoc_type_id, to_chalk_trait_id, to_foreign_def_id,
-    to_placeholder_idx,
+    lt_from_placeholder_idx, lt_to_placeholder_idx, to_assoc_type_id, to_chalk_trait_id,
+    to_foreign_def_id, to_placeholder_idx,
 };
 pub use method_resolution::check_orphan_rules;
 pub use traits::TraitEnvironment;
@@ -334,11 +335,23 @@ pub(crate) fn make_binders_with_count<T: HasInterner<Interner = Interner>>(
     generics: &Generics,
     value: T,
 ) -> Binders<T> {
-    let it = generics.iter_id().take(count).map(|id| match id {
-        Either::Left(_) => None,
-        Either::Right(id) => Some(db.const_param_ty(id)),
-    });
-    crate::make_type_and_const_binders(it, value)
+    let it = generics.iter_id().take(count);
+
+    Binders::new(
+        VariableKinds::from_iter(
+            Interner,
+            it.map(|x| match x {
+                hir_def::GenericParamId::ConstParamId(id) => {
+                    chalk_ir::VariableKind::Const(db.const_param_ty(id))
+                }
+                hir_def::GenericParamId::TypeParamId(_) => {
+                    chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)
+                }
+                hir_def::GenericParamId::LifetimeParamId(_) => chalk_ir::VariableKind::Lifetime,
+            }),
+        ),
+        value,
+    )
 }
 
 pub(crate) fn make_binders<T: HasInterner<Interner = Interner>>(
@@ -584,29 +597,34 @@ impl TypeFoldable<Interner> for CallableSig {
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
 pub enum ImplTraitId {
-    ReturnTypeImplTrait(hir_def::FunctionId, RpitId),
+    ReturnTypeImplTrait(hir_def::FunctionId, ImplTraitIdx),
+    AssociatedTypeImplTrait(hir_def::TypeAliasId, ImplTraitIdx),
     AsyncBlockTypeImplTrait(hir_def::DefWithBodyId, ExprId),
 }
 impl_intern_value_trivial!(ImplTraitId);
 
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub struct ReturnTypeImplTraits {
-    pub(crate) impl_traits: Arena<ReturnTypeImplTrait>,
+pub struct ImplTraits {
+    pub(crate) impl_traits: Arena<ImplTrait>,
 }
 
-has_interner!(ReturnTypeImplTraits);
+has_interner!(ImplTraits);
 
 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
-pub struct ReturnTypeImplTrait {
+pub struct ImplTrait {
     pub(crate) bounds: Binders<Vec<QuantifiedWhereClause>>,
 }
 
-pub type RpitId = Idx<ReturnTypeImplTrait>;
+pub type ImplTraitIdx = Idx<ImplTrait>;
 
 pub fn static_lifetime() -> Lifetime {
     LifetimeData::Static.intern(Interner)
 }
 
+pub fn error_lifetime() -> Lifetime {
+    static_lifetime()
+}
+
 pub(crate) fn fold_free_vars<T: HasInterner<Interner = Interner> + TypeFoldable<Interner>>(
     t: T,
     for_ty: impl FnMut(BoundVar, DebruijnIndex) -> Ty,
@@ -696,6 +714,55 @@ pub(crate) fn fold_tys_and_consts<T: HasInterner<Interner = Interner> + TypeFold
     t.fold_with(&mut TyFolder(f), binders)
 }
 
+pub(crate) fn fold_generic_args<T: HasInterner<Interner = Interner> + TypeFoldable<Interner>>(
+    t: T,
+    f: impl FnMut(GenericArgData, DebruijnIndex) -> GenericArgData,
+    binders: DebruijnIndex,
+) -> T {
+    use chalk_ir::fold::{TypeFolder, TypeSuperFoldable};
+    #[derive(chalk_derive::FallibleTypeFolder)]
+    #[has_interner(Interner)]
+    struct TyFolder<F: FnMut(GenericArgData, DebruijnIndex) -> GenericArgData>(F);
+    impl<F: FnMut(GenericArgData, DebruijnIndex) -> GenericArgData> TypeFolder<Interner>
+        for TyFolder<F>
+    {
+        fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner> {
+            self
+        }
+
+        fn interner(&self) -> Interner {
+            Interner
+        }
+
+        fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Ty {
+            let ty = ty.super_fold_with(self.as_dyn(), outer_binder);
+            self.0(GenericArgData::Ty(ty), outer_binder)
+                .intern(Interner)
+                .ty(Interner)
+                .unwrap()
+                .clone()
+        }
+
+        fn fold_const(&mut self, c: Const, outer_binder: DebruijnIndex) -> Const {
+            self.0(GenericArgData::Const(c), outer_binder)
+                .intern(Interner)
+                .constant(Interner)
+                .unwrap()
+                .clone()
+        }
+
+        fn fold_lifetime(&mut self, lt: Lifetime, outer_binder: DebruijnIndex) -> Lifetime {
+            let lt = lt.super_fold_with(self.as_dyn(), outer_binder);
+            self.0(GenericArgData::Lifetime(lt), outer_binder)
+                .intern(Interner)
+                .lifetime(Interner)
+                .unwrap()
+                .clone()
+        }
+    }
+    t.fold_with(&mut TyFolder(f), binders)
+}
+
 /// 'Canonicalizes' the `t` by replacing any errors with new variables. Also
 /// ensures there are no unbound variables or inference variables anywhere in
 /// the `t`.
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 dac20f22597..25ccc84c13c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
@@ -24,17 +24,20 @@ use hir_def::{
     data::adt::StructKind,
     expander::Expander,
     generics::{
-        TypeOrConstParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
+        GenericParamDataRef, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
+        WherePredicateTypeTarget,
     },
     lang_item::LangItem,
     nameres::MacroSubNs,
     path::{GenericArg, GenericArgs, ModPath, Path, PathKind, PathSegment, PathSegments},
-    resolver::{HasResolver, Resolver, TypeNs},
-    type_ref::{ConstRef, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef},
+    resolver::{HasResolver, LifetimeNs, Resolver, TypeNs},
+    type_ref::{
+        ConstRef, LifetimeRef, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound, TypeRef,
+    },
     AdtId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, FunctionId,
-    GenericDefId, HasModule, ImplId, InTypeConstLoc, ItemContainerId, LocalFieldId, Lookup,
-    ModuleDefId, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId, TypeOwnerId,
-    TypeParamId, UnionId, VariantId,
+    GenericDefId, GenericParamId, HasModule, ImplId, InTypeConstLoc, ItemContainerId, LocalFieldId,
+    Lookup, ModuleDefId, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId, TypeOwnerId,
+    UnionId, VariantId,
 };
 use hir_expand::{name::Name, ExpandResult};
 use intern::Interned;
@@ -52,18 +55,18 @@ use crate::{
         unknown_const_as_generic,
     },
     db::HirDatabase,
-    make_binders,
-    mapping::{from_chalk_trait_id, ToChalk},
+    error_lifetime, make_binders,
+    mapping::{from_chalk_trait_id, lt_to_placeholder_idx, ToChalk},
     static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
-    utils::Generics,
     utils::{
-        all_super_trait_refs, associated_type_by_name_including_super_traits, generics,
+        all_super_trait_refs, associated_type_by_name_including_super_traits, generics, Generics,
         InTypeConstIdMetadata,
     },
     AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy,
-    FnAbi, FnPointer, FnSig, FnSubst, ImplTraitId, Interner, ParamKind, PolyFnSig, ProjectionTy,
-    QuantifiedWhereClause, QuantifiedWhereClauses, ReturnTypeImplTrait, ReturnTypeImplTraits,
-    Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause,
+    FnAbi, FnPointer, FnSig, FnSubst, ImplTrait, ImplTraitId, ImplTraits, Interner, Lifetime,
+    LifetimeData, ParamKind, PolyFnSig, ProjectionTy, QuantifiedWhereClause,
+    QuantifiedWhereClauses, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder,
+    TyKind, WhereClause,
 };
 
 #[derive(Debug)]
@@ -76,7 +79,7 @@ enum ImplTraitLoweringState {
     /// we're grouping the mutable data (the counter and this field) together
     /// with the immutable context (the references to the DB and resolver).
     /// Splitting this up would be a possible fix.
-    Opaque(RefCell<Arena<ReturnTypeImplTrait>>),
+    Opaque(RefCell<Arena<ImplTrait>>),
     Param(Cell<u16>),
     Variable(Cell<u16>),
     Disallowed,
@@ -275,9 +278,11 @@ impl<'a> TyLoweringContext<'a> {
                 let inner_ty = self.lower_ty(inner);
                 TyKind::Slice(inner_ty).intern(Interner)
             }
-            TypeRef::Reference(inner, _, mutability) => {
+            TypeRef::Reference(inner, lifetime, mutability) => {
                 let inner_ty = self.lower_ty(inner);
-                let lifetime = static_lifetime();
+                // FIXME: It should infer the eldided lifetimes instead of stubbing with static
+                let lifetime =
+                    lifetime.as_ref().map_or_else(static_lifetime, |lr| self.lower_lifetime(lr));
                 TyKind::Ref(lower_to_chalk_mutability(*mutability), lifetime, inner_ty)
                     .intern(Interner)
             }
@@ -301,15 +306,18 @@ impl<'a> TyLoweringContext<'a> {
             TypeRef::ImplTrait(bounds) => {
                 match &self.impl_trait_mode {
                     ImplTraitLoweringState::Opaque(opaque_type_data) => {
-                        let func = match self.resolver.generic_def() {
-                            Some(GenericDefId::FunctionId(f)) => f,
-                            _ => panic!("opaque impl trait lowering in non-function"),
+                        let origin = match self.resolver.generic_def() {
+                            Some(GenericDefId::FunctionId(it)) => Either::Left(it),
+                            Some(GenericDefId::TypeAliasId(it)) => Either::Right(it),
+                            _ => panic!(
+                                "opaque impl trait lowering must be in function or type alias"
+                            ),
                         };
 
                         // this dance is to make sure the data is in the right
                         // place even if we encounter more opaque types while
                         // lowering the bounds
-                        let idx = opaque_type_data.borrow_mut().alloc(ReturnTypeImplTrait {
+                        let idx = opaque_type_data.borrow_mut().alloc(ImplTrait {
                             bounds: crate::make_single_type_binders(Vec::new()),
                         });
                         // We don't want to lower the bounds inside the binders
@@ -323,13 +331,17 @@ impl<'a> TyLoweringContext<'a> {
                         // away instead of two.
                         let actual_opaque_type_data = self
                             .with_debruijn(DebruijnIndex::INNERMOST, |ctx| {
-                                ctx.lower_impl_trait(bounds, func)
+                                ctx.lower_impl_trait(bounds, self.resolver.krate())
                             });
                         opaque_type_data.borrow_mut()[idx] = actual_opaque_type_data;
 
-                        let impl_trait_id = ImplTraitId::ReturnTypeImplTrait(func, idx);
+                        let impl_trait_id = origin.either(
+                            |f| ImplTraitId::ReturnTypeImplTrait(f, idx),
+                            |a| ImplTraitId::AssociatedTypeImplTrait(a, idx),
+                        );
                         let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
-                        let generics = generics(self.db.upcast(), func.into());
+                        let generics =
+                            generics(self.db.upcast(), origin.either(|f| f.into(), |a| a.into()));
                         let parameters = generics.bound_vars_subst(self.db, self.in_binders);
                         TyKind::OpaqueType(opaque_ty_id, parameters).intern(Interner)
                     }
@@ -344,13 +356,18 @@ impl<'a> TyLoweringContext<'a> {
                                 .filter(|(_, data)| {
                                     matches!(
                                         data,
-                                        TypeOrConstParamData::TypeParamData(data)
+                                        GenericParamDataRef::TypeParamData(data)
                                         if data.provenance == TypeParamProvenance::ArgumentImplTrait
                                     )
                                 })
                                 .nth(idx as usize)
                                 .map_or(TyKind::Error, |(id, _)| {
-                                    TyKind::Placeholder(to_placeholder_idx(self.db, id))
+                                    if let GenericParamId::TypeParamId(id) = id {
+                                        TyKind::Placeholder(to_placeholder_idx(self.db, id.into()))
+                                    } else {
+                                        // we just filtered them out
+                                        unreachable!("Unexpected lifetime or const argument");
+                                    }
                                 });
                             param.intern(Interner)
                         } else {
@@ -367,11 +384,12 @@ impl<'a> TyLoweringContext<'a> {
                             list_params,
                             const_params,
                             _impl_trait_params,
+                            _lifetime_params,
                         ) = if let Some(def) = self.resolver.generic_def() {
                             let generics = generics(self.db.upcast(), def);
                             generics.provenance_split()
                         } else {
-                            (0, 0, 0, 0, 0)
+                            (0, 0, 0, 0, 0, 0)
                         };
                         TyKind::BoundVar(BoundVar::new(
                             self.in_binders,
@@ -808,9 +826,16 @@ impl<'a> TyLoweringContext<'a> {
             return Substitution::empty(Interner);
         };
         let def_generics = generics(self.db.upcast(), def);
-        let (parent_params, self_params, type_params, const_params, impl_trait_params) =
-            def_generics.provenance_split();
-        let item_len = self_params + type_params + const_params + impl_trait_params;
+        let (
+            parent_params,
+            self_params,
+            type_params,
+            const_params,
+            impl_trait_params,
+            lifetime_params,
+        ) = def_generics.provenance_split();
+        let item_len =
+            self_params + type_params + const_params + impl_trait_params + lifetime_params;
         let total_len = parent_params + item_len;
 
         let ty_error = TyKind::Error.intern(Interner).cast(Interner);
@@ -825,7 +850,10 @@ impl<'a> TyLoweringContext<'a> {
                 .take(self_params)
             {
                 if let Some(id) = def_generic_iter.next() {
-                    assert!(id.is_left());
+                    assert!(matches!(
+                        id,
+                        GenericParamId::TypeParamId(_) | GenericParamId::LifetimeParamId(_)
+                    ));
                     substs.push(x);
                 }
             }
@@ -858,6 +886,7 @@ impl<'a> TyLoweringContext<'a> {
                         &mut (),
                         |_, type_ref| self.lower_ty(type_ref),
                         |_, const_ref, ty| self.lower_const(const_ref, ty),
+                        |_, lifetime_ref| self.lower_lifetime(lifetime_ref),
                     ) {
                         had_explicit_args = true;
                         substs.push(x);
@@ -867,15 +896,45 @@ impl<'a> TyLoweringContext<'a> {
                     }
                 }
             }
+
+            for arg in generic_args
+                .args
+                .iter()
+                .filter(|arg| matches!(arg, GenericArg::Lifetime(_)))
+                .take(lifetime_params)
+            {
+                // Taking into the fact that def_generic_iter will always have lifetimes at the end
+                // Should have some test cases tho to test this behaviour more properly
+                if let Some(id) = def_generic_iter.next() {
+                    if let Some(x) = generic_arg_to_chalk(
+                        self.db,
+                        id,
+                        arg,
+                        &mut (),
+                        |_, type_ref| self.lower_ty(type_ref),
+                        |_, const_ref, ty| self.lower_const(const_ref, ty),
+                        |_, lifetime_ref| self.lower_lifetime(lifetime_ref),
+                    ) {
+                        had_explicit_args = true;
+                        substs.push(x);
+                    } else {
+                        // Never return a None explicitly
+                        never!("Unexpected None by generic_arg_to_chalk");
+                    }
+                }
+            }
         } else {
             fill_self_params();
         }
 
         // These params include those of parent.
         let remaining_params: SmallVec<[_; 2]> = def_generic_iter
-            .map(|eid| match eid {
-                Either::Left(_) => ty_error.clone(),
-                Either::Right(x) => unknown_const_as_generic(self.db.const_param_ty(x)),
+            .map(|id| match id {
+                GenericParamId::ConstParamId(x) => {
+                    unknown_const_as_generic(self.db.const_param_ty(x))
+                }
+                GenericParamId::TypeParamId(_) => ty_error.clone(),
+                GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner),
             })
             .collect();
         assert_eq!(remaining_params.len() + substs.len(), total_len);
@@ -1107,8 +1166,12 @@ impl<'a> TyLoweringContext<'a> {
                     binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
                 );
                 if let Some(type_ref) = &binding.type_ref {
-                    if let (TypeRef::ImplTrait(bounds), ImplTraitLoweringState::Disallowed) =
-                        (type_ref, &self.impl_trait_mode)
+                    if let (
+                        TypeRef::ImplTrait(bounds),
+                        ImplTraitLoweringState::Param(_)
+                        | ImplTraitLoweringState::Variable(_)
+                        | ImplTraitLoweringState::Disallowed,
+                    ) = (type_ref, &self.impl_trait_mode)
                     {
                         for bound in bounds {
                             predicates.extend(
@@ -1270,11 +1333,7 @@ impl<'a> TyLoweringContext<'a> {
         }
     }
 
-    fn lower_impl_trait(
-        &self,
-        bounds: &[Interned<TypeBound>],
-        func: FunctionId,
-    ) -> ReturnTypeImplTrait {
+    fn lower_impl_trait(&self, bounds: &[Interned<TypeBound>], krate: CrateId) -> ImplTrait {
         cov_mark::hit!(lower_rpit);
         let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner);
         let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
@@ -1284,7 +1343,6 @@ impl<'a> TyLoweringContext<'a> {
                 .collect();
 
             if !ctx.unsized_types.borrow().contains(&self_ty) {
-                let krate = func.krate(ctx.db.upcast());
                 let sized_trait = ctx
                     .db
                     .lang_item(krate, LangItem::Sized)
@@ -1301,7 +1359,34 @@ impl<'a> TyLoweringContext<'a> {
             }
             predicates
         });
-        ReturnTypeImplTrait { bounds: crate::make_single_type_binders(predicates) }
+        ImplTrait { bounds: crate::make_single_type_binders(predicates) }
+    }
+
+    pub fn lower_lifetime(&self, lifetime: &LifetimeRef) -> Lifetime {
+        match self.resolver.resolve_lifetime(lifetime) {
+            Some(resolution) => match resolution {
+                LifetimeNs::Static => static_lifetime(),
+                LifetimeNs::LifetimeParam(id) => match self.type_param_mode {
+                    ParamLoweringMode::Placeholder => {
+                        LifetimeData::Placeholder(lt_to_placeholder_idx(self.db, id))
+                    }
+                    ParamLoweringMode::Variable => {
+                        let generics = generics(
+                            self.db.upcast(),
+                            self.resolver.generic_def().expect("generics in scope"),
+                        );
+                        let idx = match generics.lifetime_idx(id) {
+                            None => return error_lifetime(),
+                            Some(idx) => idx,
+                        };
+
+                        LifetimeData::BoundVar(BoundVar::new(self.in_binders, idx))
+                    }
+                }
+                .intern(Interner),
+            },
+            None => error_lifetime(),
+        }
     }
 }
 
@@ -1685,7 +1770,7 @@ pub(crate) fn generic_defaults_query(
 
     let defaults = Arc::from_iter(generic_params.iter().enumerate().map(|(idx, (id, p))| {
         match p {
-            TypeOrConstParamData::TypeParamData(p) => {
+            GenericParamDataRef::TypeParamData(p) => {
                 let mut ty =
                     p.default.as_ref().map_or(TyKind::Error.intern(Interner), |t| ctx.lower_ty(t));
                 // Each default can only refer to previous parameters.
@@ -1694,13 +1779,13 @@ pub(crate) fn generic_defaults_query(
                 ty = fallback_bound_vars(ty, idx, parent_start_idx);
                 crate::make_binders(db, &generic_params, ty.cast(Interner))
             }
-            TypeOrConstParamData::ConstParamData(p) => {
+            GenericParamDataRef::ConstParamData(p) => {
+                let GenericParamId::ConstParamId(id) = id else {
+                    unreachable!("Unexpected lifetime or type argument")
+                };
+
                 let mut val = p.default.as_ref().map_or_else(
-                    || {
-                        unknown_const_as_generic(
-                            db.const_param_ty(ConstParamId::from_unchecked(id)),
-                        )
-                    },
+                    || unknown_const_as_generic(db.const_param_ty(id)),
                     |c| {
                         let c = ctx.lower_const(c, ctx.lower_ty(&p.ty));
                         c.cast(Interner)
@@ -1710,6 +1795,10 @@ pub(crate) fn generic_defaults_query(
                 val = fallback_bound_vars(val, idx, parent_start_idx);
                 make_binders(db, &generic_params, val)
             }
+            GenericParamDataRef::LifetimeParamData(_) => {
+                // using static because it requires defaults
+                make_binders(db, &generic_params, static_lifetime().cast(Interner))
+            }
         }
     }));
 
@@ -1726,8 +1815,9 @@ pub(crate) fn generic_defaults_recover(
     // we still need one default per parameter
     let defaults = Arc::from_iter(generic_params.iter_id().map(|id| {
         let val = match id {
-            Either::Left(_) => TyKind::Error.intern(Interner).cast(Interner),
-            Either::Right(id) => unknown_const_as_generic(db.const_param_ty(id)),
+            GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner),
+            GenericParamId::ConstParamId(id) => unknown_const_as_generic(db.const_param_ty(id)),
+            GenericParamId::LifetimeParamId(_) => static_lifetime().cast(Interner),
         };
         crate::make_binders(db, &generic_params, val)
     }));
@@ -1869,6 +1959,7 @@ fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> {
     let generics = generics(db.upcast(), t.into());
     let resolver = t.resolver(db.upcast());
     let ctx = TyLoweringContext::new(db, &resolver, t.into())
+        .with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
         .with_type_param_mode(ParamLoweringMode::Variable);
     let type_alias_data = db.type_alias_data(t);
     if type_alias_data.is_extern {
@@ -2029,7 +2120,7 @@ pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<
 pub(crate) fn return_type_impl_traits(
     db: &dyn HirDatabase,
     def: hir_def::FunctionId,
-) -> Option<Arc<Binders<ReturnTypeImplTraits>>> {
+) -> Option<Arc<Binders<ImplTraits>>> {
     // FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe
     let data = db.function_data(def);
     let resolver = def.resolver(db.upcast());
@@ -2038,7 +2129,7 @@ pub(crate) fn return_type_impl_traits(
         .with_type_param_mode(ParamLoweringMode::Variable);
     let _ret = ctx_ret.lower_ty(&data.ret_type);
     let generics = generics(db.upcast(), def.into());
-    let return_type_impl_traits = ReturnTypeImplTraits {
+    let return_type_impl_traits = ImplTraits {
         impl_traits: match ctx_ret.impl_trait_mode {
             ImplTraitLoweringState::Opaque(x) => x.into_inner(),
             _ => unreachable!(),
@@ -2051,6 +2142,32 @@ pub(crate) fn return_type_impl_traits(
     }
 }
 
+pub(crate) fn type_alias_impl_traits(
+    db: &dyn HirDatabase,
+    def: hir_def::TypeAliasId,
+) -> Option<Arc<Binders<ImplTraits>>> {
+    let data = db.type_alias_data(def);
+    let resolver = def.resolver(db.upcast());
+    let ctx = TyLoweringContext::new(db, &resolver, def.into())
+        .with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
+        .with_type_param_mode(ParamLoweringMode::Variable);
+    if let Some(type_ref) = &data.type_ref {
+        let _ty = ctx.lower_ty(type_ref);
+    }
+    let generics = generics(db.upcast(), def.into());
+    let type_alias_impl_traits = ImplTraits {
+        impl_traits: match ctx.impl_trait_mode {
+            ImplTraitLoweringState::Opaque(x) => x.into_inner(),
+            _ => unreachable!(),
+        },
+    };
+    if type_alias_impl_traits.impl_traits.is_empty() {
+        None
+    } else {
+        Some(Arc::new(make_binders(db, &generics, type_alias_impl_traits)))
+    }
+}
+
 pub(crate) fn lower_to_chalk_mutability(m: hir_def::type_ref::Mutability) -> Mutability {
     match m {
         hir_def::type_ref::Mutability::Shared => Mutability::Not,
@@ -2064,23 +2181,29 @@ pub(crate) fn lower_to_chalk_mutability(m: hir_def::type_ref::Mutability) -> Mut
 /// Returns `Some` of the lowered generic arg. `None` if the provided arg is a lifetime.
 pub(crate) fn generic_arg_to_chalk<'a, T>(
     db: &dyn HirDatabase,
-    kind_id: Either<TypeParamId, ConstParamId>,
+    kind_id: GenericParamId,
     arg: &'a GenericArg,
     this: &mut T,
     for_type: impl FnOnce(&mut T, &TypeRef) -> Ty + 'a,
     for_const: impl FnOnce(&mut T, &ConstRef, Ty) -> Const + 'a,
+    for_lifetime: impl FnOnce(&mut T, &LifetimeRef) -> Lifetime + 'a,
 ) -> Option<crate::GenericArg> {
     let kind = match kind_id {
-        Either::Left(_) => ParamKind::Type,
-        Either::Right(id) => {
+        GenericParamId::TypeParamId(_) => ParamKind::Type,
+        GenericParamId::ConstParamId(id) => {
             let ty = db.const_param_ty(id);
             ParamKind::Const(ty)
         }
+        GenericParamId::LifetimeParamId(_) => ParamKind::Lifetime,
     };
     Some(match (arg, kind) {
         (GenericArg::Type(type_ref), ParamKind::Type) => for_type(this, type_ref).cast(Interner),
         (GenericArg::Const(c), ParamKind::Const(c_ty)) => for_const(this, c, c_ty).cast(Interner),
+        (GenericArg::Lifetime(lifetime_ref), ParamKind::Lifetime) => {
+            for_lifetime(this, lifetime_ref).cast(Interner)
+        }
         (GenericArg::Const(_), ParamKind::Type) => TyKind::Error.intern(Interner).cast(Interner),
+        (GenericArg::Lifetime(_), ParamKind::Type) => TyKind::Error.intern(Interner).cast(Interner),
         (GenericArg::Type(t), ParamKind::Const(c_ty)) => {
             // We want to recover simple idents, which parser detects them
             // as types. Maybe here is not the best place to do it, but
@@ -2096,7 +2219,9 @@ pub(crate) fn generic_arg_to_chalk<'a, T>(
             }
             unknown_const_as_generic(c_ty)
         }
-        (GenericArg::Lifetime(_), _) => return None,
+        (GenericArg::Lifetime(_), ParamKind::Const(c_ty)) => unknown_const_as_generic(c_ty),
+        (GenericArg::Type(_), ParamKind::Lifetime) => error_lifetime().cast(Interner),
+        (GenericArg::Const(_), ParamKind::Lifetime) => error_lifetime().cast(Interner),
     })
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs
index fba760974f2..c61d8277142 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mapping.rs
@@ -151,6 +151,14 @@ pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> L
     db.lookup_intern_lifetime_param_id(interned_id)
 }
 
+pub fn lt_to_placeholder_idx(db: &dyn HirDatabase, id: LifetimeParamId) -> PlaceholderIndex {
+    let interned_id = db.intern_lifetime_param_id(id);
+    PlaceholderIndex {
+        ui: chalk_ir::UniverseIndex::ROOT,
+        idx: salsa::InternKey::as_intern_id(&interned_id).as_usize(),
+    }
+}
+
 pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId {
     chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id))
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
index a679a114b4b..73b07df56f7 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs
@@ -4,7 +4,7 @@
 //! and the corresponding code mostly in rustc_hir_analysis/check/method/probe.rs.
 use std::ops::ControlFlow;
 
-use base_db::{CrateId, Edition};
+use base_db::CrateId;
 use chalk_ir::{cast::Cast, Mutability, TyKind, UniverseIndex, WhereClause};
 use hir_def::{
     data::{adt::StructFlags, ImplData},
@@ -15,6 +15,7 @@ use hir_def::{
 use hir_expand::name::Name;
 use rustc_hash::{FxHashMap, FxHashSet};
 use smallvec::{smallvec, SmallVec};
+use span::Edition;
 use stdx::never;
 use triomphe::Arc;
 
@@ -643,7 +644,7 @@ pub fn is_dyn_method(
     let ItemContainerId::TraitId(trait_id) = func.lookup(db.upcast()).container else {
         return None;
     };
-    let trait_params = db.generic_params(trait_id.into()).type_or_consts.len();
+    let trait_params = db.generic_params(trait_id.into()).len();
     let fn_params = fn_subst.len(Interner) - trait_params;
     let trait_ref = TraitRef {
         trait_id: to_chalk_trait_id(trait_id),
@@ -685,7 +686,7 @@ pub(crate) fn lookup_impl_method_query(
     let ItemContainerId::TraitId(trait_id) = func.lookup(db.upcast()).container else {
         return (func, fn_subst);
     };
-    let trait_params = db.generic_params(trait_id.into()).type_or_consts.len();
+    let trait_params = db.generic_params(trait_id.into()).len();
     let fn_params = fn_subst.len(Interner) - trait_params;
     let trait_ref = TraitRef {
         trait_id: to_chalk_trait_id(trait_id),
@@ -966,7 +967,7 @@ pub fn iterate_method_candidates_dyn(
             // the methods by autoderef order of *receiver types*, not *self
             // types*.
 
-            let mut table = InferenceTable::new(db, env.clone());
+            let mut table = InferenceTable::new(db, env);
             let ty = table.instantiate_canonical(ty.clone());
             let deref_chain = autoderef_method_receiver(&mut table, ty);
 
@@ -1044,7 +1045,7 @@ fn iterate_method_candidates_with_autoref(
     let ref_muted = Canonical {
         value: TyKind::Ref(Mutability::Mut, static_lifetime(), receiver_ty.value.clone())
             .intern(Interner),
-        binders: receiver_ty.binders.clone(),
+        binders: receiver_ty.binders,
     };
 
     iterate_method_candidates_by_receiver(ref_muted, first_adjustment.with_autoref(Mutability::Mut))
@@ -1060,7 +1061,7 @@ fn iterate_method_candidates_by_receiver(
     name: Option<&Name>,
     mut callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
 ) -> ControlFlow<()> {
-    let receiver_ty = table.instantiate_canonical(receiver_ty.clone());
+    let receiver_ty = table.instantiate_canonical(receiver_ty);
     // We're looking for methods with *receiver* type receiver_ty. These could
     // be found in any of the derefs of receiver_ty, so we have to go through
     // that, including raw derefs.
@@ -1456,7 +1457,7 @@ fn is_valid_trait_method_candidate(
                 if let Some(receiver_ty) = receiver_ty {
                     check_that!(data.has_self_param());
 
-                    let fn_subst = TyBuilder::subst_for_def(db, fn_id, Some(impl_subst.clone()))
+                    let fn_subst = TyBuilder::subst_for_def(db, fn_id, Some(impl_subst))
                         .fill_with_inference_vars(table)
                         .build();
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
index fd98141af63..045ffb418c8 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
@@ -1931,7 +1931,11 @@ impl Evaluator<'_> {
             ty: &Ty,
             locals: &Locals,
             mm: &mut ComplexMemoryMap,
+            stack_depth_limit: usize,
         ) -> Result<()> {
+            if stack_depth_limit.checked_sub(1).is_none() {
+                return Err(MirEvalError::StackOverflow);
+            }
             match ty.kind(Interner) {
                 TyKind::Ref(_, _, t) => {
                     let size = this.size_align_of(t, locals)?;
@@ -1970,7 +1974,14 @@ impl Evaluator<'_> {
                             if let Some(ty) = check_inner {
                                 for i in 0..count {
                                     let offset = element_size * i;
-                                    rec(this, &b[offset..offset + element_size], ty, locals, mm)?;
+                                    rec(
+                                        this,
+                                        &b[offset..offset + element_size],
+                                        ty,
+                                        locals,
+                                        mm,
+                                        stack_depth_limit - 1,
+                                    )?;
                                 }
                             }
                         }
@@ -1984,7 +1995,14 @@ impl Evaluator<'_> {
                     let size = this.size_of_sized(inner, locals, "inner of array")?;
                     for i in 0..len {
                         let offset = i * size;
-                        rec(this, &bytes[offset..offset + size], inner, locals, mm)?;
+                        rec(
+                            this,
+                            &bytes[offset..offset + size],
+                            inner,
+                            locals,
+                            mm,
+                            stack_depth_limit - 1,
+                        )?;
                     }
                 }
                 chalk_ir::TyKind::Tuple(_, subst) => {
@@ -1993,7 +2011,14 @@ impl Evaluator<'_> {
                         let ty = ty.assert_ty_ref(Interner); // Tuple only has type argument
                         let offset = layout.fields.offset(id).bytes_usize();
                         let size = this.layout(ty)?.size.bytes_usize();
-                        rec(this, &bytes[offset..offset + size], ty, locals, mm)?;
+                        rec(
+                            this,
+                            &bytes[offset..offset + size],
+                            ty,
+                            locals,
+                            mm,
+                            stack_depth_limit - 1,
+                        )?;
                     }
                 }
                 chalk_ir::TyKind::Adt(adt, subst) => match adt.0 {
@@ -2008,7 +2033,14 @@ impl Evaluator<'_> {
                                 .bytes_usize();
                             let ty = &field_types[f].clone().substitute(Interner, subst);
                             let size = this.layout(ty)?.size.bytes_usize();
-                            rec(this, &bytes[offset..offset + size], ty, locals, mm)?;
+                            rec(
+                                this,
+                                &bytes[offset..offset + size],
+                                ty,
+                                locals,
+                                mm,
+                                stack_depth_limit - 1,
+                            )?;
                         }
                     }
                     AdtId::EnumId(e) => {
@@ -2027,7 +2059,14 @@ impl Evaluator<'_> {
                                     l.fields.offset(u32::from(f.into_raw()) as usize).bytes_usize();
                                 let ty = &field_types[f].clone().substitute(Interner, subst);
                                 let size = this.layout(ty)?.size.bytes_usize();
-                                rec(this, &bytes[offset..offset + size], ty, locals, mm)?;
+                                rec(
+                                    this,
+                                    &bytes[offset..offset + size],
+                                    ty,
+                                    locals,
+                                    mm,
+                                    stack_depth_limit - 1,
+                                )?;
                             }
                         }
                     }
@@ -2038,7 +2077,7 @@ impl Evaluator<'_> {
             Ok(())
         }
         let mut mm = ComplexMemoryMap::default();
-        rec(self, bytes, ty, locals, &mut mm)?;
+        rec(self, bytes, ty, locals, &mut mm, self.stack_depth_limit - 1)?;
         Ok(mm)
     }
 
@@ -2317,7 +2356,7 @@ impl Evaluator<'_> {
 
     fn exec_fn_with_args(
         &mut self,
-        def: FunctionId,
+        mut def: FunctionId,
         args: &[IntervalAndTy],
         generic_args: Substitution,
         locals: &Locals,
@@ -2335,6 +2374,9 @@ impl Evaluator<'_> {
         )? {
             return Ok(None);
         }
+        if let Some(redirect_def) = self.detect_and_redirect_special_function(def)? {
+            def = redirect_def;
+        }
         let arg_bytes = args.iter().map(|it| IntervalOrOwned::Borrowed(it.interval));
         match self.get_mir_or_dyn_index(def, generic_args.clone(), locals, span)? {
             MirOrDynIndex::Dyn(self_ty_idx) => {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
index 628a1fe2d28..d4d669182f2 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
@@ -13,7 +13,7 @@ use crate::mir::eval::{
     name, pad16, static_lifetime, Address, AdtId, Arc, BuiltinType, Evaluator, FunctionId,
     HasModule, HirDisplay, Interned, InternedClosure, Interner, Interval, IntervalAndTy,
     IntervalOrOwned, ItemContainerId, LangItem, Layout, Locals, Lookup, MirEvalError, MirSpan,
-    ModPath, Mutability, Result, Substitution, Ty, TyBuilder, TyExt,
+    Mutability, Result, Substitution, Ty, TyBuilder, TyExt,
 };
 
 mod simd;
@@ -158,6 +158,25 @@ impl Evaluator<'_> {
         Ok(false)
     }
 
+    pub(super) fn detect_and_redirect_special_function(
+        &mut self,
+        def: FunctionId,
+    ) -> Result<Option<FunctionId>> {
+        // `PanicFmt` is redirected to `ConstPanicFmt`
+        if let Some(LangItem::PanicFmt) = self.db.lang_attr(def.into()) {
+            let resolver =
+                self.db.crate_def_map(self.crate_id).crate_root().resolver(self.db.upcast());
+
+            let Some(hir_def::lang_item::LangItemTarget::Function(const_panic_fmt)) =
+                self.db.lang_item(resolver.krate(), LangItem::ConstPanicFmt)
+            else {
+                not_supported!("const_panic_fmt lang item not found or not a function");
+            };
+            return Ok(Some(const_panic_fmt));
+        }
+        Ok(None)
+    }
+
     /// Clone has special impls for tuples and function pointers
     fn exec_clone(
         &mut self,
@@ -291,9 +310,14 @@ impl Evaluator<'_> {
         use LangItem::*;
         let candidate = self.db.lang_attr(def.into())?;
         // We want to execute these functions with special logic
-        if [PanicFmt, BeginPanic, SliceLen, DropInPlace].contains(&candidate) {
+        // `PanicFmt` is not detected here as it's redirected later.
+        if [BeginPanic, SliceLen, DropInPlace].contains(&candidate) {
             return Some(candidate);
         }
+        if self.db.attrs(def.into()).by_key("rustc_const_panic_str").exists() {
+            // `#[rustc_const_panic_str]` is treated like `lang = "begin_panic"` by rustc CTFE.
+            return Some(LangItem::BeginPanic);
+        }
         None
     }
 
@@ -309,43 +333,6 @@ impl Evaluator<'_> {
         let mut args = args.iter();
         match it {
             BeginPanic => Err(MirEvalError::Panic("<unknown-panic-payload>".to_owned())),
-            PanicFmt => {
-                let message = (|| {
-                    let resolver = self
-                        .db
-                        .crate_def_map(self.crate_id)
-                        .crate_root()
-                        .resolver(self.db.upcast());
-                    let Some(format_fn) = resolver.resolve_path_in_value_ns_fully(
-                        self.db.upcast(),
-                        &hir_def::path::Path::from_known_path_with_no_generic(
-                            ModPath::from_segments(
-                                hir_expand::mod_path::PathKind::Abs,
-                                [name![std], name![fmt], name![format]],
-                            ),
-                        ),
-                    ) else {
-                        not_supported!("std::fmt::format not found");
-                    };
-                    let hir_def::resolver::ValueNs::FunctionId(format_fn) = format_fn else {
-                        not_supported!("std::fmt::format is not a function")
-                    };
-                    let interval = self.interpret_mir(
-                        self.db
-                            .mir_body(format_fn.into())
-                            .map_err(|e| MirEvalError::MirLowerError(format_fn, e))?,
-                        args.map(|x| IntervalOrOwned::Owned(x.clone())),
-                    )?;
-                    let message_string = interval.get(self)?;
-                    let addr =
-                        Address::from_bytes(&message_string[self.ptr_size()..2 * self.ptr_size()])?;
-                    let size = from_bytes!(usize, message_string[2 * self.ptr_size()..]);
-                    Ok(std::string::String::from_utf8_lossy(self.read_memory(addr, size)?)
-                        .into_owned())
-                })()
-                .unwrap_or_else(|e| format!("Failed to render panic format args: {e:?}"));
-                Err(MirEvalError::Panic(message))
-            }
             SliceLen => {
                 let arg = args.next().ok_or(MirEvalError::InternalError(
                     "argument of <[T]>::len() is not provided".into(),
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs
index d2e413f0a33..d6557c3a816 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs
@@ -82,6 +82,9 @@ impl FallibleTypeFolder<Interner> for Filler<'_> {
                         };
                         filler.try_fold_ty(infer.type_of_rpit[idx].clone(), outer_binder)
                     }
+                    crate::ImplTraitId::AssociatedTypeImplTrait(..) => {
+                        not_supported!("associated type impl trait");
+                    }
                     crate::ImplTraitId::AsyncBlockTypeImplTrait(_, _) => {
                         not_supported!("async block impl trait");
                     }
@@ -181,8 +184,16 @@ impl Filler<'_> {
                                     self.generics
                                         .as_ref()
                                         .and_then(|it| it.iter().nth(b.index))
-                                        .unwrap()
-                                        .0,
+                                        .and_then(|(id, _)| match id {
+                                            hir_def::GenericParamId::ConstParamId(id) => {
+                                                Some(hir_def::TypeOrConstParamId::from(id))
+                                            }
+                                            hir_def::GenericParamId::TypeParamId(id) => {
+                                                Some(hir_def::TypeOrConstParamId::from(id))
+                                            }
+                                            _ => None,
+                                        })
+                                        .unwrap(),
                                     self.subst.clone(),
                                 )
                             })?
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs
index d699067b5a6..2a46becbfda 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs
@@ -298,7 +298,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
             if let Some(syntax_ptr) = body_source_map.self_param_syntax() {
                 let root = db.parse_or_expand(syntax_ptr.file_id);
                 let node = syntax_ptr.map(|ptr| ptr.to_node(&root).syntax().clone());
-                types.push((node.clone(), ty));
+                types.push((node, ty));
             }
         }
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs
index e75b037e38d..50692674996 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/display_source_code.rs
@@ -85,7 +85,7 @@ fn render_dyn_for_ty() {
 trait Foo<'a> {}
 
 fn foo(foo: &dyn for<'a> Foo<'a>) {}
-    // ^^^ &dyn Foo
+    // ^^^ &dyn Foo<'static>
 "#,
     );
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs
index 963b4a2aba0..80d5a0ae001 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/patterns.rs
@@ -1109,7 +1109,7 @@ fn var_args() {
 #[lang = "va_list"]
 pub struct VaListImpl<'f>;
 fn my_fn(foo: ...) {}
-       //^^^ VaListImpl<'_>
+       //^^^ VaListImpl<'static>
 "#,
     );
 }
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 9a8ebd07d01..8565b60210b 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
@@ -896,13 +896,13 @@ fn flush(&self) {
 "#,
         expect![[r#"
             123..127 'self': &Mutex<T>
-            150..152 '{}': MutexGuard<'_, T>
+            150..152 '{}': MutexGuard<'static, T>
             234..238 'self': &{unknown}
             240..290 '{     ...()); }': ()
             250..251 'w': &Mutex<BufWriter>
             276..287 '*(w.lock())': BufWriter
             278..279 'w': &Mutex<BufWriter>
-            278..286 'w.lock()': MutexGuard<'_, BufWriter>
+            278..286 'w.lock()': MutexGuard<'static, BufWriter>
         "#]],
     );
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs
index 917e9f44085..f39404593e5 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/simple.rs
@@ -3092,7 +3092,7 @@ fn main() {
             389..394 'boxed': Box<Foo<i32>>
             389..406 'boxed....nner()': &i32
             416..421 'good1': &i32
-            424..438 'Foo::get_inner': fn get_inner<i32>(&Box<Foo<i32>>) -> &i32
+            424..438 'Foo::get_inner': fn get_inner<i32, 'static>(&Box<Foo<i32>>) -> &i32
             424..446 'Foo::g...boxed)': &i32
             439..445 '&boxed': &Box<Foo<i32>>
             440..445 'boxed': Box<Foo<i32>>
@@ -3100,7 +3100,7 @@ fn main() {
             464..469 'boxed': Box<Foo<i32>>
             464..480 'boxed....self()': &Foo<i32>
             490..495 'good2': &Foo<i32>
-            498..511 'Foo::get_self': fn get_self<i32>(&Box<Foo<i32>>) -> &Foo<i32>
+            498..511 'Foo::get_self': fn get_self<i32, 'static>(&Box<Foo<i32>>) -> &Foo<i32>
             498..519 'Foo::g...boxed)': &Foo<i32>
             512..518 '&boxed': &Box<Foo<i32>>
             513..518 'boxed': Box<Foo<i32>>
@@ -3659,7 +3659,7 @@ fn main() {
     let are = "are";
     let count = 10;
     builtin#format_args("hello {count:02} {} friends, we {are:?} {0}{last}", "fancy", last = "!");
- // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type: Arguments<'_>
+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type: Arguments<'static>
 }
 "#,
     );
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
index b80cfe18e4c..759af18c98b 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
@@ -1279,6 +1279,40 @@ fn bar() {
 }
 
 #[test]
+fn argument_assoc_impl_trait() {
+    check_infer(
+        r#"
+trait Outer {
+    type Item;
+}
+
+trait Inner { }
+
+fn foo<T: Outer<Item = impl Inner>>(baz: T) {
+}
+
+impl Outer for usize {
+    type Item = usize;
+}
+
+impl Inner for usize {}
+
+fn main() {
+    foo(2);
+}
+"#,
+        expect![[r#"
+            85..88 'baz': T
+            93..96 '{ }': ()
+            182..197 '{     foo(2); }': ()
+            188..191 'foo': fn foo<usize>(usize)
+            188..194 'foo(2)': ()
+            192..193 '2': usize
+        "#]],
+    );
+}
+
+#[test]
 fn simple_return_pos_impl_trait() {
     cov_mark::check!(lower_rpit);
     check_infer(
@@ -4655,3 +4689,78 @@ fn f<T: Send, U>() {
 "#,
     );
 }
+
+#[test]
+fn associated_type_impl_trait() {
+    check_types(
+        r#"
+trait Foo {}
+struct S1;
+impl Foo for S1 {}
+
+trait Bar {
+    type Item;
+    fn bar(&self) -> Self::Item;
+}
+struct S2;
+impl Bar for S2 {
+    type Item = impl Foo;
+    fn bar(&self) -> Self::Item {
+        S1
+    }
+}
+
+fn test() {
+    let x = S2.bar();
+      //^ impl Foo + ?Sized
+}
+        "#,
+    );
+}
+
+#[test]
+fn associated_type_impl_traits_complex() {
+    check_types(
+        r#"
+struct Unary<T>(T);
+struct Binary<T, U>(T, U);
+
+trait Foo {}
+struct S1;
+impl Foo for S1 {}
+
+trait Bar {
+    type Item;
+    fn bar(&self) -> Unary<Self::Item>;
+}
+struct S2;
+impl Bar for S2 {
+    type Item = Unary<impl Foo>;
+    fn bar(&self) -> Unary<<Self as Bar>::Item> {
+        Unary(Unary(S1))
+    }
+}
+
+trait Baz {
+    type Target1;
+    type Target2;
+    fn baz(&self) -> Binary<Self::Target1, Self::Target2>;
+}
+struct S3;
+impl Baz for S3 {
+    type Target1 = impl Foo;
+    type Target2 = Unary<impl Bar>;
+    fn baz(&self) -> Binary<Self::Target1, Self::Target2> {
+        Binary(S1, Unary(S2))
+    }
+}
+
+fn test() {
+    let x = S3.baz();
+      //^ Binary<impl Foo + ?Sized, Unary<impl Bar + ?Sized>>
+    let y = x.1.0.bar();
+      //^ Unary<Bar::Item<impl Bar + ?Sized>>
+}
+        "#,
+    );
+}
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 8bd57820d2c..afd4d1f271d 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
@@ -9,18 +9,18 @@ use chalk_ir::{
     fold::{FallibleTypeFolder, Shift},
     BoundVar, DebruijnIndex,
 };
-use either::Either;
 use hir_def::{
     db::DefDatabase,
     generics::{
-        GenericParams, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
-        WherePredicateTypeTarget,
+        GenericParamDataRef, GenericParams, LifetimeParamData, TypeOrConstParamData,
+        TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
     },
     lang_item::LangItem,
     resolver::{HasResolver, TypeNs},
     type_ref::{TraitBoundModifier, TypeRef},
-    ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, ItemContainerId, Lookup,
-    OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId,
+    ConstParamId, EnumId, EnumVariantId, FunctionId, GenericDefId, GenericParamId, ItemContainerId,
+    LifetimeParamId, Lookup, OpaqueInternableThing, TraitId, TypeAliasId, TypeOrConstParamId,
+    TypeParamId,
 };
 use hir_expand::name::Name;
 use intern::Interned;
@@ -270,64 +270,130 @@ pub(crate) struct Generics {
 }
 
 impl Generics {
-    pub(crate) fn iter_id(&self) -> impl Iterator<Item = Either<TypeParamId, ConstParamId>> + '_ {
-        self.iter().map(|(id, data)| match data {
-            TypeOrConstParamData::TypeParamData(_) => Either::Left(TypeParamId::from_unchecked(id)),
-            TypeOrConstParamData::ConstParamData(_) => {
-                Either::Right(ConstParamId::from_unchecked(id))
-            }
-        })
+    pub(crate) fn iter_id(&self) -> impl Iterator<Item = GenericParamId> + '_ {
+        self.iter().map(|(id, _)| id)
     }
 
     /// Iterator over types and const params of self, then parent.
     pub(crate) fn iter<'a>(
         &'a self,
-    ) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
-        let to_toc_id = |it: &'a Generics| {
-            move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p)
+    ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'a>)> + 'a {
+        let from_toc_id = |it: &'a Generics| {
+            move |(local_id, p): (_, &'a TypeOrConstParamData)| {
+                let id = TypeOrConstParamId { parent: it.def, local_id };
+                match p {
+                    TypeOrConstParamData::TypeParamData(p) => (
+                        GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
+                        GenericParamDataRef::TypeParamData(p),
+                    ),
+                    TypeOrConstParamData::ConstParamData(p) => (
+                        GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
+                        GenericParamDataRef::ConstParamData(p),
+                    ),
+                }
+            }
         };
-        self.params.iter().map(to_toc_id(self)).chain(self.iter_parent())
+
+        let from_lt_id = |it: &'a Generics| {
+            move |(local_id, p): (_, &'a LifetimeParamData)| {
+                (
+                    GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
+                    GenericParamDataRef::LifetimeParamData(p),
+                )
+            }
+        };
+
+        let lt_iter = self.params.iter_lt().map(from_lt_id(self));
+        self.params.iter().map(from_toc_id(self)).chain(lt_iter).chain(self.iter_parent())
     }
 
     /// Iterate over types and const params without parent params.
     pub(crate) fn iter_self<'a>(
         &'a self,
-    ) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &'a TypeOrConstParamData)> + 'a {
-        let to_toc_id = |it: &'a Generics| {
-            move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p)
+    ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'a>)> + 'a {
+        let from_toc_id = |it: &'a Generics| {
+            move |(local_id, p): (_, &'a TypeOrConstParamData)| {
+                let id = TypeOrConstParamId { parent: it.def, local_id };
+                match p {
+                    TypeOrConstParamData::TypeParamData(p) => (
+                        GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
+                        GenericParamDataRef::TypeParamData(p),
+                    ),
+                    TypeOrConstParamData::ConstParamData(p) => (
+                        GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
+                        GenericParamDataRef::ConstParamData(p),
+                    ),
+                }
+            }
+        };
+
+        let from_lt_id = |it: &'a Generics| {
+            move |(local_id, p): (_, &'a LifetimeParamData)| {
+                (
+                    GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
+                    GenericParamDataRef::LifetimeParamData(p),
+                )
+            }
         };
-        self.params.iter().map(to_toc_id(self))
+
+        self.params.iter().map(from_toc_id(self)).chain(self.params.iter_lt().map(from_lt_id(self)))
     }
 
     /// Iterator over types and const params of parent.
-    pub(crate) fn iter_parent(
-        &self,
-    ) -> impl DoubleEndedIterator<Item = (TypeOrConstParamId, &TypeOrConstParamData)> {
+    #[allow(clippy::needless_lifetimes)]
+    pub(crate) fn iter_parent<'a>(
+        &'a self,
+    ) -> impl DoubleEndedIterator<Item = (GenericParamId, GenericParamDataRef<'a>)> + 'a {
         self.parent_generics().into_iter().flat_map(|it| {
-            let to_toc_id =
-                move |(local_id, p)| (TypeOrConstParamId { parent: it.def, local_id }, p);
-            it.params.iter().map(to_toc_id)
+            let from_toc_id = move |(local_id, p): (_, &'a TypeOrConstParamData)| {
+                let id = TypeOrConstParamId { parent: it.def, local_id };
+                match p {
+                    TypeOrConstParamData::TypeParamData(p) => (
+                        GenericParamId::TypeParamId(TypeParamId::from_unchecked(id)),
+                        GenericParamDataRef::TypeParamData(p),
+                    ),
+                    TypeOrConstParamData::ConstParamData(p) => (
+                        GenericParamId::ConstParamId(ConstParamId::from_unchecked(id)),
+                        GenericParamDataRef::ConstParamData(p),
+                    ),
+                }
+            };
+
+            let from_lt_id = move |(local_id, p): (_, &'a LifetimeParamData)| {
+                (
+                    GenericParamId::LifetimeParamId(LifetimeParamId { parent: it.def, local_id }),
+                    GenericParamDataRef::LifetimeParamData(p),
+                )
+            };
+            let lt_iter = it.params.iter_lt().map(from_lt_id);
+            it.params.iter().map(from_toc_id).chain(lt_iter)
         })
     }
 
     /// Returns total number of generic parameters in scope, including those from parent.
     pub(crate) fn len(&self) -> usize {
         let parent = self.parent_generics().map_or(0, Generics::len);
-        let child = self.params.type_or_consts.len();
+        let child = self.params.len();
         parent + child
     }
 
-    /// Returns numbers of generic parameters excluding those from parent.
+    /// Returns numbers of generic parameters and lifetimes excluding those from parent.
     pub(crate) fn len_self(&self) -> usize {
+        self.params.len()
+    }
+
+    /// Returns number of generic parameter excluding those from parent
+    fn len_params(&self) -> usize {
         self.params.type_or_consts.len()
     }
 
-    /// (parent total, self param, type param list, const param list, impl trait)
-    pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize) {
+    /// (parent total, self param, type params, const params, impl trait list, lifetimes)
+    pub(crate) fn provenance_split(&self) -> (usize, usize, usize, usize, usize, usize) {
         let mut self_params = 0;
         let mut type_params = 0;
         let mut impl_trait_params = 0;
         let mut const_params = 0;
+        let mut lifetime_params = 0;
         self.params.iter().for_each(|(_, data)| match data {
             TypeOrConstParamData::TypeParamData(p) => match p.provenance {
                 TypeParamProvenance::TypeParamList => type_params += 1,
@@ -337,8 +403,10 @@ impl Generics {
             TypeOrConstParamData::ConstParamData(_) => const_params += 1,
         });
 
+        self.params.iter_lt().for_each(|(_, _)| lifetime_params += 1);
+
         let parent_len = self.parent_generics().map_or(0, Generics::len);
-        (parent_len, self_params, type_params, const_params, impl_trait_params)
+        (parent_len, self_params, type_params, const_params, impl_trait_params, lifetime_params)
     }
 
     pub(crate) fn param_idx(&self, param: TypeOrConstParamId) -> Option<usize> {
@@ -358,6 +426,26 @@ impl Generics {
         }
     }
 
+    pub(crate) fn lifetime_idx(&self, lifetime: LifetimeParamId) -> Option<usize> {
+        Some(self.find_lifetime(lifetime)?.0)
+    }
+
+    fn find_lifetime(&self, lifetime: LifetimeParamId) -> Option<(usize, &LifetimeParamData)> {
+        if lifetime.parent == self.def {
+            let (idx, (_local_id, data)) = self
+                .params
+                .iter_lt()
+                .enumerate()
+                .find(|(_, (idx, _))| *idx == lifetime.local_id)?;
+
+            Some((self.len_params() + idx, data))
+        } else {
+            self.parent_generics()
+                .and_then(|g| g.find_lifetime(lifetime))
+                .map(|(idx, data)| (self.len_self() + idx, data))
+        }
+    }
+
     pub(crate) fn parent_generics(&self) -> Option<&Generics> {
         self.parent_generics.as_deref()
     }
@@ -371,10 +459,15 @@ impl Generics {
         Substitution::from_iter(
             Interner,
             self.iter_id().enumerate().map(|(idx, id)| match id {
-                Either::Left(_) => BoundVar::new(debruijn, idx).to_ty(Interner).cast(Interner),
-                Either::Right(id) => BoundVar::new(debruijn, idx)
+                GenericParamId::ConstParamId(id) => BoundVar::new(debruijn, idx)
                     .to_const(Interner, db.const_param_ty(id))
                     .cast(Interner),
+                GenericParamId::TypeParamId(_) => {
+                    BoundVar::new(debruijn, idx).to_ty(Interner).cast(Interner)
+                }
+                GenericParamId::LifetimeParamId(_) => {
+                    BoundVar::new(debruijn, idx).to_lifetime(Interner).cast(Interner)
+                }
             }),
         )
     }
@@ -384,12 +477,15 @@ impl Generics {
         Substitution::from_iter(
             Interner,
             self.iter_id().map(|id| match id {
-                Either::Left(id) => {
+                GenericParamId::TypeParamId(id) => {
                     crate::to_placeholder_idx(db, id.into()).to_ty(Interner).cast(Interner)
                 }
-                Either::Right(id) => crate::to_placeholder_idx(db, id.into())
+                GenericParamId::ConstParamId(id) => crate::to_placeholder_idx(db, id.into())
                     .to_const(Interner, db.const_param_ty(id))
                     .cast(Interner),
+                GenericParamId::LifetimeParamId(id) => {
+                    crate::lt_to_placeholder_idx(db, id).to_lifetime(Interner).cast(Interner)
+                }
             }),
         )
     }
diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs
index c5d44c11f2c..23c6b078b96 100644
--- a/src/tools/rust-analyzer/crates/hir/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/display.rs
@@ -186,18 +186,29 @@ impl HirDisplay for Struct {
             }
             StructKind::Record => {
                 let has_where_clause = write_where_clause(def_id, f)?;
-                let fields = self.fields(f.db);
-                f.write_char(if !has_where_clause { ' ' } else { '\n' })?;
-                if fields.is_empty() {
-                    f.write_str("{}")?;
-                } else {
-                    f.write_str("{\n")?;
-                    for field in self.fields(f.db) {
-                        f.write_str("    ")?;
-                        field.hir_fmt(f)?;
-                        f.write_str(",\n")?;
+                if let Some(limit) = f.entity_limit {
+                    let fields = self.fields(f.db);
+                    let count = fields.len().min(limit);
+                    f.write_char(if !has_where_clause { ' ' } else { '\n' })?;
+                    if count == 0 {
+                        if fields.is_empty() {
+                            f.write_str("{}")?;
+                        } else {
+                            f.write_str("{ /* … */ }")?;
+                        }
+                    } else {
+                        f.write_str(" {\n")?;
+                        for field in &fields[..count] {
+                            f.write_str("    ")?;
+                            field.hir_fmt(f)?;
+                            f.write_str(",\n")?;
+                        }
+
+                        if fields.len() > count {
+                            f.write_str("    /* … */\n")?;
+                        }
+                        f.write_str("}")?;
                     }
-                    f.write_str("}")?;
                 }
             }
             StructKind::Unit => _ = write_where_clause(def_id, f)?,
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index b922aa8e46d..106056c2fc3 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -38,7 +38,7 @@ mod display;
 use std::{iter, mem::discriminant, ops::ControlFlow};
 
 use arrayvec::ArrayVec;
-use base_db::{CrateDisplayName, CrateId, CrateOrigin, Edition, FileId};
+use base_db::{CrateDisplayName, CrateId, CrateOrigin, FileId};
 use either::Either;
 use hir_def::{
     body::{BodyDiagnostic, SyntheticSyntax},
@@ -65,7 +65,7 @@ use hir_ty::{
     consteval::{try_const_usize, unknown_const_as_generic, ConstExt},
     db::InternedClosure,
     diagnostics::BodyValidationDiagnostic,
-    known_const_to_ast,
+    error_lifetime, known_const_to_ast,
     layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding},
     method_resolution::{self, TyFingerprint},
     mir::{interpret_mir, MutBorrowKind},
@@ -79,6 +79,7 @@ use hir_ty::{
 use itertools::Itertools;
 use nameres::diagnostics::DefDiagnosticKind;
 use rustc_hash::FxHashSet;
+use span::Edition;
 use stdx::{impl_from, never};
 use syntax::{
     ast::{self, HasAttrs as _, HasName},
@@ -971,7 +972,7 @@ fn precise_macro_call_location(
                 MacroKind::ProcMacro,
             )
         }
-        MacroCallKind::Derive { ast_id, derive_attr_index, derive_index } => {
+        MacroCallKind::Derive { ast_id, derive_attr_index, derive_index, .. } => {
             let node = ast_id.to_node(db.upcast());
             // Compute the precise location of the macro name's token in the derive
             // list.
@@ -1099,13 +1100,14 @@ impl Field {
             VariantDef::Union(it) => it.id.into(),
             VariantDef::Variant(it) => it.parent_enum(db).id.into(),
         };
-        let mut generics = generics.map(|it| it.ty.clone());
+        let mut generics = generics.map(|it| it.ty);
         let substs = TyBuilder::subst_for_def(db, def_id, None)
             .fill(|x| match x {
                 ParamKind::Type => {
                     generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)).cast(Interner)
                 }
                 ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
+                ParamKind::Lifetime => error_lifetime().cast(Interner),
             })
             .build();
         let ty = db.field_types(var_id)[self.id].clone().substitute(Interner, &substs);
@@ -1416,7 +1418,7 @@ impl Adt {
     }
 
     pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
-        if db.generic_params(self.into()).iter().count() != 0 {
+        if !db.generic_params(self.into()).is_empty() {
             return Err(LayoutError::HasPlaceholder);
         }
         let krate = self.krate(db).id;
@@ -1440,13 +1442,14 @@ impl Adt {
     /// the greatest API, FIXME find a better one.
     pub fn ty_with_args(self, db: &dyn HirDatabase, args: impl Iterator<Item = Type>) -> Type {
         let id = AdtId::from(self);
-        let mut it = args.map(|t| t.ty.clone());
+        let mut it = args.map(|t| t.ty);
         let ty = TyBuilder::def_ty(db, id.into(), None)
             .fill(|x| {
                 let r = it.next().unwrap_or_else(|| TyKind::Error.intern(Interner));
                 match x {
                     ParamKind::Type => r.cast(Interner),
                     ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
+                    ParamKind::Lifetime => error_lifetime().cast(Interner),
                 }
             })
             .build();
@@ -1859,12 +1862,13 @@ impl Function {
             ItemContainerId::TraitId(it) => Some(it.into()),
             ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None,
         };
-        let mut generics = generics.map(|it| it.ty.clone());
+        let mut generics = generics.map(|it| it.ty);
         let mut filler = |x: &_| match x {
             ParamKind::Type => {
                 generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)).cast(Interner)
             }
             ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
+            ParamKind::Lifetime => error_lifetime().cast(Interner),
         };
 
         let parent_substs =
@@ -1954,7 +1958,7 @@ impl Function {
             ItemContainerId::TraitId(it) => Some(it.into()),
             ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None,
         };
-        let mut generics = generics.map(|it| it.ty.clone());
+        let mut generics = generics.map(|it| it.ty);
         let parent_substs = parent_id.map(|id| {
             TyBuilder::subst_for_def(db, id, None)
                 .fill(|x| match x {
@@ -1963,6 +1967,7 @@ impl Function {
                         .unwrap_or_else(|| TyKind::Error.intern(Interner))
                         .cast(Interner),
                     ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
+                    ParamKind::Lifetime => error_lifetime().cast(Interner),
                 })
                 .build()
         });
@@ -2007,8 +2012,7 @@ impl Function {
         }
         let data = db.function_data(self.id);
 
-        data.name.to_smol_str() == "main"
-            || data.attrs.export_name().map(core::ops::Deref::deref) == Some("main")
+        data.name.to_smol_str() == "main" || data.attrs.export_name() == Some("main")
     }
 
     /// Does this function have the ignore attribute?
@@ -2215,12 +2219,13 @@ impl SelfParam {
             }
         };
 
-        let mut generics = generics.map(|it| it.ty.clone());
+        let mut generics = generics.map(|it| it.ty);
         let mut filler = |x: &_| match x {
             ParamKind::Type => {
                 generics.next().unwrap_or_else(|| TyKind::Error.intern(Interner)).cast(Interner)
             }
             ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
+            ParamKind::Lifetime => error_lifetime().cast(Interner),
         };
 
         let parent_substs = TyBuilder::subst_for_def(db, parent_id, None).fill(&mut filler).build();
@@ -2592,7 +2597,7 @@ impl Macro {
             },
             MacroId::ProcMacroId(it) => match it.lookup(db.upcast()).kind {
                 ProcMacroKind::CustomDerive => MacroKind::Derive,
-                ProcMacroKind::FuncLike => MacroKind::ProcMacro,
+                ProcMacroKind::Bang => MacroKind::ProcMacro,
                 ProcMacroKind::Attr => MacroKind::Attr,
             },
         }
@@ -3628,16 +3633,41 @@ impl Impl {
                     .filter(filter),
             );
         }
+
+        if let Some(block) =
+            ty.adt_id(Interner).and_then(|def| def.0.module(db.upcast()).containing_block())
+        {
+            if let Some(inherent_impls) = db.inherent_impls_in_block(block) {
+                all.extend(
+                    inherent_impls.for_self_ty(&ty).iter().cloned().map(Self::from).filter(filter),
+                );
+            }
+            if let Some(trait_impls) = db.trait_impls_in_block(block) {
+                all.extend(
+                    trait_impls
+                        .for_self_ty_without_blanket_impls(fp)
+                        .map(Self::from)
+                        .filter(filter),
+                );
+            }
+        }
+
         all
     }
 
     pub fn all_for_trait(db: &dyn HirDatabase, trait_: Trait) -> Vec<Impl> {
-        let krate = trait_.module(db).krate();
+        let module = trait_.module(db);
+        let krate = module.krate();
         let mut all = Vec::new();
         for Crate { id } in krate.transitive_reverse_dependencies(db) {
             let impls = db.trait_impls_in_crate(id);
             all.extend(impls.for_trait(trait_.id).map(Self::from))
         }
+        if let Some(block) = module.id.containing_block() {
+            if let Some(trait_impls) = db.trait_impls_in_block(block) {
+                all.extend(trait_impls.for_trait(trait_.id).map(Self::from));
+            }
+        }
         all
     }
 
@@ -3683,7 +3713,7 @@ impl Impl {
         let macro_file = src.file_id.macro_file()?;
         let loc = macro_file.macro_call_id.lookup(db.upcast());
         let (derive_attr, derive_index) = match loc.kind {
-            MacroCallKind::Derive { ast_id, derive_attr_index, derive_index } => {
+            MacroCallKind::Derive { ast_id, derive_attr_index, derive_index, .. } => {
                 let module_id = self.id.lookup(db.upcast()).container;
                 (
                     db.crate_def_map(module_id.krate())[module_id.local_id]
@@ -4114,6 +4144,7 @@ impl Type {
                         // FIXME: this code is not covered in tests.
                         unknown_const_as_generic(ty.clone())
                     }
+                    ParamKind::Lifetime => error_lifetime().cast(Interner),
                 }
             })
             .build();
@@ -4144,6 +4175,7 @@ impl Type {
                 match it {
                     ParamKind::Type => args.next().unwrap().ty.clone().cast(Interner),
                     ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
+                    ParamKind::Lifetime => error_lifetime().cast(Interner),
                 }
             })
             .build();
diff --git a/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs b/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs
index 102e0ca4c3d..63b2a2506f8 100644
--- a/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs
@@ -177,7 +177,7 @@ pub(super) fn type_constructor<'a, DB: HirDatabase>(
                 // Note that we need special case for 0 param constructors because of multi cartesian
                 // product
                 let variant_exprs: Vec<Expr> = if param_exprs.is_empty() {
-                    vec![Expr::Variant { variant, generics: generics.clone(), params: Vec::new() }]
+                    vec![Expr::Variant { variant, generics, params: Vec::new() }]
                 } else {
                     param_exprs
                         .into_iter()
@@ -462,7 +462,7 @@ pub(super) fn free_function<'a, DB: HirDatabase>(
 
 /// # Impl method tactic
 ///
-/// Attempts to to call methods on types from lookup table.
+/// Attempts to call methods on types from lookup table.
 /// This includes both functions from direct impl blocks as well as functions from traits.
 /// Methods defined in impl blocks that are generic and methods that are themselves have
 /// generics are ignored for performance reasons.
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
index d111005c2ec..65ce3e822c5 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
@@ -5617,7 +5617,7 @@ fn func<T: Debug>(i: Struct<'_, T>) {
     fun_name(i);
 }
 
-fn $0fun_name(i: Struct<'_, T>) {
+fn $0fun_name(i: Struct<'static, T>) {
     foo(i);
 }
 "#,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs
index 38f40b8d58b..2150003bc14 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs
@@ -614,7 +614,7 @@ struct Foo<'a, T> {
 }
 
 impl<'a, T> Foo<'a, T> {
-    $0fn bar(self, mut b: Vec<&'a Bar<'_, T>>) -> &'a Bar<'_, T> {
+    $0fn bar(self, mut b: Vec<&'a Bar<'a, T>>) -> &'a Bar<'a, T> {
         self.field.bar(b)
     }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs
index 24a1f9492e2..a4f092cc498 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs
@@ -961,11 +961,11 @@ struct Foo { field: i32 }
 impl Foo { fn foo(&self) { $0 } }"#,
             expect![[r#"
                 fd self.field i32
+                me self.foo() fn(&self)
                 lc self       &Foo
                 sp Self       Foo
                 st Foo        Foo
                 bt u32        u32
-                me self.foo() fn(&self)
             "#]],
         );
         check(
@@ -975,11 +975,11 @@ struct Foo(i32);
 impl Foo { fn foo(&mut self) { $0 } }"#,
             expect![[r#"
                 fd self.0     i32
+                me self.foo() fn(&mut self)
                 lc self       &mut Foo
                 sp Self       Foo
                 st Foo        Foo
                 bt u32        u32
-                me self.foo() fn(&mut self)
             "#]],
         );
     }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs
index 79467841502..c48672e80ac 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list/trait_impl.rs
@@ -186,11 +186,11 @@ fn add_function_impl(
         if func.assoc_fn_params(ctx.db).is_empty() { "" } else { ".." }
     );
 
-    let completion_kind = if func.has_self_param(ctx.db) {
-        CompletionItemKind::Method
+    let completion_kind = CompletionItemKind::SymbolKind(if func.has_self_param(ctx.db) {
+        SymbolKind::Method
     } else {
-        CompletionItemKind::SymbolKind(SymbolKind::Function)
-    };
+        SymbolKind::Function
+    });
 
     let mut item = CompletionItem::new(completion_kind, replacement_range, label);
     item.lookup_by(format!("fn {}", fn_name.display(ctx.db)))
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs
index ed32a5db23e..1322c05e30e 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/keyword.rs
@@ -75,8 +75,8 @@ impl Future for A {}
 fn foo(a: A) { a.$0 }
 "#,
             expect![[r#"
-                kw await                  expr.await
                 me into_future() (as IntoFuture) fn(self) -> <Self as IntoFuture>::IntoFuture
+                kw await                  expr.await
                 sn box                    Box::new(expr)
                 sn call                   function(expr)
                 sn dbg                    dbg!(expr)
@@ -102,8 +102,8 @@ fn foo() {
 }
 "#,
             expect![[r#"
-                kw await                  expr.await
                 me into_future() (use core::future::IntoFuture) fn(self) -> <Self as IntoFuture>::IntoFuture
+                kw await                  expr.await
                 sn box                    Box::new(expr)
                 sn call                   function(expr)
                 sn dbg                    dbg!(expr)
@@ -131,8 +131,8 @@ impl IntoFuture for A {}
 fn foo(a: A) { a.$0 }
 "#,
             expect![[r#"
-                kw await                  expr.await
                 me into_future() (as IntoFuture) fn(self) -> <Self as IntoFuture>::IntoFuture
+                kw await                  expr.await
                 sn box                    Box::new(expr)
                 sn call                   function(expr)
                 sn dbg                    dbg!(expr)
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 aa22155feff..995e3f48253 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
@@ -540,7 +540,7 @@ impl CompletionContext<'_> {
     /// Whether the given trait is an operator trait or not.
     pub(crate) fn is_ops_trait(&self, trait_: hir::Trait) -> bool {
         match trait_.attrs(self.db).lang() {
-            Some(lang) => OP_TRAIT_LANG_NAMES.contains(&lang.as_str()),
+            Some(lang) => OP_TRAIT_LANG_NAMES.contains(&lang),
             None => false,
         }
     }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
index 357060817c7..b9a2c383bdd 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
@@ -342,7 +342,6 @@ pub enum CompletionItemKind {
     BuiltinType,
     InferredType,
     Keyword,
-    Method,
     Snippet,
     UnresolvedReference,
     Expression,
@@ -369,6 +368,7 @@ impl CompletionItemKind {
                 SymbolKind::LifetimeParam => "lt",
                 SymbolKind::Local => "lc",
                 SymbolKind::Macro => "ma",
+                SymbolKind::Method => "me",
                 SymbolKind::ProcMacro => "pm",
                 SymbolKind::Module => "md",
                 SymbolKind::SelfParam => "sp",
@@ -388,7 +388,6 @@ impl CompletionItemKind {
             CompletionItemKind::BuiltinType => "bt",
             CompletionItemKind::InferredType => "it",
             CompletionItemKind::Keyword => "kw",
-            CompletionItemKind::Method => "me",
             CompletionItemKind::Snippet => "sn",
             CompletionItemKind::UnresolvedReference => "??",
             CompletionItemKind::Expression => "ex",
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 6d1a5a0bc52..ca0424809ed 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
@@ -312,7 +312,7 @@ pub(crate) fn render_expr(
         None => ctx.source_range(),
     };
 
-    let mut item = CompletionItem::new(CompletionItemKind::Expression, source_range, label.clone());
+    let mut item = CompletionItem::new(CompletionItemKind::Expression, source_range, label);
 
     let snippet = format!(
         "{}$0",
@@ -677,10 +677,11 @@ mod tests {
 
     #[track_caller]
     fn check_function_relevance(ra_fixture: &str, expect: Expect) {
-        let actual: Vec<_> = do_completion(ra_fixture, CompletionItemKind::Method)
-            .into_iter()
-            .map(|item| (item.detail.unwrap_or_default(), item.relevance.function))
-            .collect();
+        let actual: Vec<_> =
+            do_completion(ra_fixture, CompletionItemKind::SymbolKind(SymbolKind::Method))
+                .into_iter()
+                .map(|item| (item.detail.unwrap_or_default(), item.relevance.function))
+                .collect();
 
         expect.assert_debug_eq(&actual);
     }
@@ -1392,7 +1393,10 @@ impl S {
     /// Method docs
     fn bar(self) { self.$0 }
 }"#,
-            &[CompletionItemKind::Method, CompletionItemKind::SymbolKind(SymbolKind::Field)],
+            &[
+                CompletionItemKind::SymbolKind(SymbolKind::Method),
+                CompletionItemKind::SymbolKind(SymbolKind::Field),
+            ],
             expect![[r#"
                 [
                     CompletionItem {
@@ -1400,7 +1404,9 @@ impl S {
                         source_range: 94..94,
                         delete: 94..94,
                         insert: "bar()$0",
-                        kind: Method,
+                        kind: SymbolKind(
+                            Method,
+                        ),
                         lookup: "bar",
                         detail: "fn(self)",
                         documentation: Documentation(
@@ -1520,7 +1526,7 @@ impl S {
 }
 fn foo(s: S) { s.$0 }
 "#,
-            CompletionItemKind::Method,
+            CompletionItemKind::SymbolKind(SymbolKind::Method),
             expect![[r#"
                 [
                     CompletionItem {
@@ -1528,7 +1534,9 @@ fn foo(s: S) { s.$0 }
                         source_range: 81..81,
                         delete: 81..81,
                         insert: "the_method()$0",
-                        kind: Method,
+                        kind: SymbolKind(
+                            Method,
+                        ),
                         lookup: "the_method",
                         detail: "fn(&self)",
                         relevance: CompletionRelevance {
@@ -2408,7 +2416,10 @@ impl Foo { fn baz(&self) -> u32 { 0 } }
 
 fn foo(f: Foo) { let _: &u32 = f.b$0 }
 "#,
-            &[CompletionItemKind::Method, CompletionItemKind::SymbolKind(SymbolKind::Field)],
+            &[
+                CompletionItemKind::SymbolKind(SymbolKind::Method),
+                CompletionItemKind::SymbolKind(SymbolKind::Field),
+            ],
             expect![[r#"
                 [
                     CompletionItem {
@@ -2416,7 +2427,9 @@ fn foo(f: Foo) { let _: &u32 = f.b$0 }
                         source_range: 109..110,
                         delete: 109..110,
                         insert: "baz()$0",
-                        kind: Method,
+                        kind: SymbolKind(
+                            Method,
+                        ),
                         lookup: "baz",
                         detail: "fn(&self) -> u32",
                         relevance: CompletionRelevance {
@@ -2631,7 +2644,7 @@ fn main() {
     let _: bool = (9 > 2).not$0;
 }
     "#,
-            &[CompletionItemKind::Snippet, CompletionItemKind::Method],
+            &[CompletionItemKind::Snippet, CompletionItemKind::SymbolKind(SymbolKind::Method)],
             expect![[r#"
                 sn not [snippet]
                 me not() (use ops::Not) [type_could_unify+requires_import]
@@ -2664,7 +2677,7 @@ fn main() {
     S.$0
 }
     "#,
-            &[CompletionItemKind::Snippet, CompletionItemKind::Method],
+            &[CompletionItemKind::Snippet, CompletionItemKind::SymbolKind(SymbolKind::Method)],
             expect![[r#"
                 me f() []
                 sn ref []
@@ -2907,7 +2920,7 @@ fn main() {
 }
 "#,
             &[
-                CompletionItemKind::Method,
+                CompletionItemKind::SymbolKind(SymbolKind::Method),
                 CompletionItemKind::SymbolKind(SymbolKind::Field),
                 CompletionItemKind::SymbolKind(SymbolKind::Function),
             ],
@@ -2918,7 +2931,9 @@ fn main() {
                         source_range: 193..193,
                         delete: 193..193,
                         insert: "flush()$0",
-                        kind: Method,
+                        kind: SymbolKind(
+                            Method,
+                        ),
                         lookup: "flush",
                         detail: "fn(&self)",
                         relevance: CompletionRelevance {
@@ -2941,7 +2956,9 @@ fn main() {
                         source_range: 193..193,
                         delete: 193..193,
                         insert: "write()$0",
-                        kind: Method,
+                        kind: SymbolKind(
+                            Method,
+                        ),
                         lookup: "write",
                         detail: "fn(&self)",
                         relevance: CompletionRelevance {
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 cf9fe1ab307..1634b0a9206 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
@@ -68,11 +68,11 @@ fn render(
     };
     let has_self_param = func.self_param(db).is_some();
     let mut item = CompletionItem::new(
-        if has_self_param {
-            CompletionItemKind::Method
+        CompletionItemKind::SymbolKind(if has_self_param {
+            SymbolKind::Method
         } else {
-            CompletionItemKind::SymbolKind(SymbolKind::Function)
-        },
+            SymbolKind::Function
+        }),
         ctx.source_range(),
         call.clone(),
     );
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
index 7749fac40b9..a653314233d 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
@@ -127,6 +127,7 @@ impl Unit {
             en Enum         Enum
             fn function()   fn()
             fn local_func() fn()
+            me self.foo()   fn(self)
             lc self         Unit
             ma makro!(…)    macro_rules! makro
             md module
@@ -166,7 +167,6 @@ impl Unit {
             kw use
             kw while
             kw while let
-            me self.foo()   fn(self)
             sn macro_rules
             sn pd
             sn ppd
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/predicate.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/predicate.rs
index 46a3e97d3e9..3718dff56e8 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/predicate.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/predicate.rs
@@ -19,7 +19,7 @@ struct Foo<'lt, T, const C: usize> where $0 {}
             en Enum      Enum
             ma makro!(…) macro_rules! makro
             md module
-            st Foo<…>    Foo<'_, {unknown}, _>
+            st Foo<…>    Foo<'static, {unknown}, _>
             st Record    Record
             st Tuple     Tuple
             st Unit      Unit
@@ -92,7 +92,7 @@ struct Foo<'lt, T, const C: usize> where for<'a> $0 {}
             en Enum      Enum
             ma makro!(…) macro_rules! makro
             md module
-            st Foo<…>    Foo<'_, {unknown}, _>
+            st Foo<…>    Foo<'static, {unknown}, _>
             st Record    Record
             st Tuple     Tuple
             st Unit      Unit
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs
index ff32eccfbff..69d8fe91040 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs
@@ -1,6 +1,7 @@
 //! Tests that don't fit into a specific category.
 
 use expect_test::{expect, Expect};
+use ide_db::SymbolKind;
 
 use crate::{
     tests::{
@@ -316,15 +317,15 @@ trait Sub: Super {
 fn foo<T: Sub>() { T::$0 }
 "#,
         expect![[r#"
-                ct C2 (as Sub)           const C2: ()
-                ct CONST (as Super)      const CONST: u8
-                fn func() (as Super)     fn()
-                fn subfunc() (as Sub)    fn()
-                ta SubTy (as Sub)        type SubTy
-                ta Ty (as Super)         type Ty
-                me method(…) (as Super)  fn(&self)
-                me submethod(…) (as Sub) fn(&self)
-            "#]],
+            ct C2 (as Sub)           const C2: ()
+            ct CONST (as Super)      const CONST: u8
+            fn func() (as Super)     fn()
+            fn subfunc() (as Sub)    fn()
+            me method(…) (as Super)  fn(&self)
+            me submethod(…) (as Sub) fn(&self)
+            ta SubTy (as Sub)        type SubTy
+            ta Ty (as Super)         type Ty
+        "#]],
     );
 }
 
@@ -356,15 +357,15 @@ impl<T> Sub for Wrap<T> {
 }
 "#,
         expect![[r#"
-                ct C2 (as Sub)           const C2: ()
-                ct CONST (as Super)      const CONST: u8
-                fn func() (as Super)     fn()
-                fn subfunc() (as Sub)    fn()
-                ta SubTy (as Sub)        type SubTy
-                ta Ty (as Super)         type Ty
-                me method(…) (as Super)  fn(&self)
-                me submethod(…) (as Sub) fn(&self)
-            "#]],
+            ct C2 (as Sub)           const C2: ()
+            ct CONST (as Super)      const CONST: u8
+            fn func() (as Super)     fn()
+            fn subfunc() (as Sub)    fn()
+            me method(…) (as Super)  fn(&self)
+            me submethod(…) (as Sub) fn(&self)
+            ta SubTy (as Sub)        type SubTy
+            ta Ty (as Super)         type Ty
+        "#]],
     );
 }
 
@@ -555,10 +556,10 @@ impl Foo {
 }
 "#,
         expect![[r#"
-                ev Bar    Bar
-                ev Baz    Baz
-                me foo(…) fn(self)
-            "#]],
+            me foo(…) fn(self)
+            ev Bar    Bar
+            ev Baz    Baz
+        "#]],
     );
 }
 
@@ -1399,7 +1400,7 @@ fn main() {
     bar.b$0
 }
 "#,
-        CompletionItemKind::Method,
+        CompletionItemKind::SymbolKind(SymbolKind::Method),
         expect!("const fn(&'foo mut self, &Foo) -> !"),
         expect!("pub const fn baz<'foo>(&'foo mut self, x: &'foo Foo) -> !"),
     );
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs
index db4ac9381ce..97709728656 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs
@@ -20,8 +20,8 @@ struct Foo<'lt, T, const C: usize> {
             en Enum      Enum
             ma makro!(…) macro_rules! makro
             md module
-            sp Self      Foo<'_, {unknown}, _>
-            st Foo<…>    Foo<'_, {unknown}, _>
+            sp Self      Foo<'static, {unknown}, _>
+            st Foo<…>    Foo<'static, {unknown}, _>
             st Record    Record
             st Tuple     Tuple
             st Unit      Unit
@@ -45,8 +45,8 @@ struct Foo<'lt, T, const C: usize>(f$0);
             en Enum       Enum
             ma makro!(…)  macro_rules! makro
             md module
-            sp Self       Foo<'_, {unknown}, _>
-            st Foo<…>     Foo<'_, {unknown}, _>
+            sp Self       Foo<'static, {unknown}, _>
+            st Foo<…>     Foo<'static, {unknown}, _>
             st Record     Record
             st Tuple      Tuple
             st Unit       Unit
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 0d5a93f7b8e..357209ceb0b 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
@@ -346,6 +346,7 @@ pub enum SymbolKind {
     Enum,
     Field,
     Function,
+    Method,
     Impl,
     Label,
     LifetimeParam,
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml b/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml
index 8ccea99e9e1..edd05009332 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml
@@ -26,6 +26,7 @@ text-edit.workspace = true
 cfg.workspace = true
 hir.workspace = true
 ide-db.workspace = true
+paths.workspace = true
 
 [dev-dependencies]
 expect-test = "1.4.0"
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs
index 67daa172b27..045154614f8 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs
@@ -23,6 +23,7 @@ mod tests {
         },
         DiagnosticsConfig,
     };
+    use test_utils::skip_slow_tests;
 
     #[track_caller]
     fn check_diagnostics_no_bails(ra_fixture: &str) {
@@ -1004,6 +1005,32 @@ fn f() {
         );
     }
 
+    #[test]
+    fn exponential_match() {
+        if skip_slow_tests() {
+            return;
+        }
+        // Constructs a match where match checking takes exponential time. Ensures we bail early.
+        use std::fmt::Write;
+        let struct_arity = 50;
+        let mut code = String::new();
+        write!(code, "struct BigStruct {{").unwrap();
+        for i in 0..struct_arity {
+            write!(code, "  field{i}: bool,").unwrap();
+        }
+        write!(code, "}}").unwrap();
+        write!(code, "fn big_match(s: BigStruct) {{").unwrap();
+        write!(code, "  match s {{").unwrap();
+        for i in 0..struct_arity {
+            write!(code, "    BigStruct {{ field{i}: true, ..}} => {{}},").unwrap();
+            write!(code, "    BigStruct {{ field{i}: false, ..}} => {{}},").unwrap();
+        }
+        write!(code, "    _ => {{}},").unwrap();
+        write!(code, "  }}").unwrap();
+        write!(code, "}}").unwrap();
+        check_diagnostics_no_bails(&code);
+    }
+
     mod rust_unstable {
         use super::*;
 
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mutability_errors.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mutability_errors.rs
index 34a0038295f..00352266ddb 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mutability_errors.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/mutability_errors.rs
@@ -7,7 +7,11 @@ use crate::{fix, Diagnostic, DiagnosticCode, DiagnosticsContext};
 // Diagnostic: need-mut
 //
 // This diagnostic is triggered on mutating an immutable variable.
-pub(crate) fn need_mut(ctx: &DiagnosticsContext<'_>, d: &hir::NeedMut) -> Diagnostic {
+pub(crate) fn need_mut(ctx: &DiagnosticsContext<'_>, d: &hir::NeedMut) -> Option<Diagnostic> {
+    if d.span.file_id.macro_file().is_some() {
+        // FIXME: Our infra can't handle allow from within macro expansions rn
+        return None;
+    }
     let fixes = (|| {
         if d.local.is_ref(ctx.sema.db) {
             // There is no simple way to add `mut` to `ref x` and `ref mut x`
@@ -29,24 +33,30 @@ pub(crate) fn need_mut(ctx: &DiagnosticsContext<'_>, d: &hir::NeedMut) -> Diagno
             use_range,
         )])
     })();
-    Diagnostic::new_with_syntax_node_ptr(
-        ctx,
-        // FIXME: `E0384` is not the only error that this diagnostic handles
-        DiagnosticCode::RustcHardError("E0384"),
-        format!(
-            "cannot mutate immutable variable `{}`",
-            d.local.name(ctx.sema.db).display(ctx.sema.db)
-        ),
-        d.span,
+    Some(
+        Diagnostic::new_with_syntax_node_ptr(
+            ctx,
+            // FIXME: `E0384` is not the only error that this diagnostic handles
+            DiagnosticCode::RustcHardError("E0384"),
+            format!(
+                "cannot mutate immutable variable `{}`",
+                d.local.name(ctx.sema.db).display(ctx.sema.db)
+            ),
+            d.span,
+        )
+        .with_fixes(fixes),
     )
-    .with_fixes(fixes)
 }
 
 // Diagnostic: unused-mut
 //
 // This diagnostic is triggered when a mutable variable isn't actually mutated.
-pub(crate) fn unused_mut(ctx: &DiagnosticsContext<'_>, d: &hir::UnusedMut) -> Diagnostic {
+pub(crate) fn unused_mut(ctx: &DiagnosticsContext<'_>, d: &hir::UnusedMut) -> Option<Diagnostic> {
     let ast = d.local.primary_source(ctx.sema.db).syntax_ptr();
+    if ast.file_id.macro_file().is_some() {
+        // FIXME: Our infra can't handle allow from within macro expansions rn
+        return None;
+    }
     let fixes = (|| {
         let file_id = ast.file_id.file_id()?;
         let mut edit_builder = TextEdit::builder();
@@ -70,14 +80,16 @@ pub(crate) fn unused_mut(ctx: &DiagnosticsContext<'_>, d: &hir::UnusedMut) -> Di
         )])
     })();
     let ast = d.local.primary_source(ctx.sema.db).syntax_ptr();
-    Diagnostic::new_with_syntax_node_ptr(
-        ctx,
-        DiagnosticCode::RustcLint("unused_mut"),
-        "variable does not need to be mutable",
-        ast,
+    Some(
+        Diagnostic::new_with_syntax_node_ptr(
+            ctx,
+            DiagnosticCode::RustcLint("unused_mut"),
+            "variable does not need to be mutable",
+            ast,
+        )
+        .experimental() // Not supporting `#[allow(unused_mut)]` in proc macros leads to false positive.
+        .with_fixes(fixes),
     )
-    .experimental() // Not supporting `#[allow(unused_mut)]` in proc macros leads to false positive.
-    .with_fixes(fixes)
 }
 
 pub(super) fn token(parent: &SyntaxNode, kind: SyntaxKind) -> Option<SyntaxToken> {
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_trailing_return.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_trailing_return.rs
index 7a040e46e33..d831878044d 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_trailing_return.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_trailing_return.rs
@@ -12,7 +12,12 @@ use crate::{adjusted_display_range, fix, Diagnostic, DiagnosticCode, Diagnostics
 pub(crate) fn remove_trailing_return(
     ctx: &DiagnosticsContext<'_>,
     d: &RemoveTrailingReturn,
-) -> Diagnostic {
+) -> Option<Diagnostic> {
+    if d.return_expr.file_id.macro_file().is_some() {
+        // FIXME: Our infra can't handle allow from within macro expansions rn
+        return None;
+    }
+
     let display_range = adjusted_display_range(ctx, d.return_expr, &|return_expr| {
         return_expr
             .syntax()
@@ -20,12 +25,14 @@ pub(crate) fn remove_trailing_return(
             .and_then(ast::ExprStmt::cast)
             .map(|stmt| stmt.syntax().text_range())
     });
-    Diagnostic::new(
-        DiagnosticCode::Clippy("needless_return"),
-        "replace return <expr>; with <expr>",
-        display_range,
+    Some(
+        Diagnostic::new(
+            DiagnosticCode::Clippy("needless_return"),
+            "replace return <expr>; with <expr>",
+            display_range,
+        )
+        .with_fixes(fixes(ctx, d)),
     )
-    .with_fixes(fixes(ctx, d))
 }
 
 fn fixes(ctx: &DiagnosticsContext<'_>, d: &RemoveTrailingReturn) -> Option<Vec<Assist>> {
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs
index f68e6982385..448df1ca163 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs
@@ -21,23 +21,30 @@ use crate::{
 pub(crate) fn remove_unnecessary_else(
     ctx: &DiagnosticsContext<'_>,
     d: &RemoveUnnecessaryElse,
-) -> Diagnostic {
+) -> Option<Diagnostic> {
+    if d.if_expr.file_id.macro_file().is_some() {
+        // FIXME: Our infra can't handle allow from within macro expansions rn
+        return None;
+    }
+
     let display_range = adjusted_display_range(ctx, d.if_expr, &|if_expr| {
         if_expr.else_token().as_ref().map(SyntaxToken::text_range)
     });
-    Diagnostic::new(
-        DiagnosticCode::Ra("remove-unnecessary-else", Severity::WeakWarning),
-        "remove unnecessary else block",
-        display_range,
+    Some(
+        Diagnostic::new(
+            DiagnosticCode::Ra("remove-unnecessary-else", Severity::WeakWarning),
+            "remove unnecessary else block",
+            display_range,
+        )
+        .experimental()
+        .with_fixes(fixes(ctx, d)),
     )
-    .experimental()
-    .with_fixes(fixes(ctx, d))
 }
 
 fn fixes(ctx: &DiagnosticsContext<'_>, d: &RemoveUnnecessaryElse) -> Option<Vec<Assist>> {
     let root = ctx.sema.db.parse_or_expand(d.if_expr.file_id);
     let if_expr = d.if_expr.value.to_node(&root);
-    let if_expr = ctx.sema.original_ast_node(if_expr.clone())?;
+    let if_expr = ctx.sema.original_ast_node(if_expr)?;
 
     let mut indent = IndentLevel::from_node(if_expr.syntax());
     let has_parent_if_expr = if_expr.syntax().parent().and_then(ast::IfExpr::cast).is_some();
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs
index becc24ab21e..b9327f85567 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs
@@ -8,6 +8,7 @@ use ide_db::{
     source_change::SourceChange,
     RootDatabase,
 };
+use paths::Utf8Component;
 use syntax::{
     ast::{self, edit::IndentLevel, HasModuleItem, HasName},
     AstNode, TextRange,
@@ -84,10 +85,10 @@ fn fixes(ctx: &DiagnosticsContext<'_>, file_id: FileId) -> Option<Vec<Assist>> {
 
         // try resolving the relative difference of the paths as inline modules
         let mut current = root_module;
-        for ele in rel.as_ref().components() {
+        for ele in rel.as_utf8_path().components() {
             let seg = match ele {
-                std::path::Component::Normal(seg) => seg.to_str()?,
-                std::path::Component::RootDir => continue,
+                Utf8Component::Normal(seg) => seg,
+                Utf8Component::RootDir => continue,
                 // shouldn't occur
                 _ => continue 'crates,
             };
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs
index a9e1d07d7c5..cd251faab9a 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unused_variables.rs
@@ -14,18 +14,24 @@ use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
 pub(crate) fn unused_variables(
     ctx: &DiagnosticsContext<'_>,
     d: &hir::UnusedVariable,
-) -> Diagnostic {
+) -> Option<Diagnostic> {
     let ast = d.local.primary_source(ctx.sema.db).syntax_ptr();
+    if ast.file_id.macro_file().is_some() {
+        // FIXME: Our infra can't handle allow from within macro expansions rn
+        return None;
+    }
     let diagnostic_range = ctx.sema.diagnostics_display_range(ast);
     let var_name = d.local.primary_source(ctx.sema.db).syntax().to_string();
-    Diagnostic::new_with_syntax_node_ptr(
-        ctx,
-        DiagnosticCode::RustcLint("unused_variables"),
-        "unused variable",
-        ast,
+    Some(
+        Diagnostic::new_with_syntax_node_ptr(
+            ctx,
+            DiagnosticCode::RustcLint("unused_variables"),
+            "unused variable",
+            ast,
+        )
+        .with_fixes(fixes(&var_name, diagnostic_range, ast.file_id.is_macro()))
+        .experimental(),
     )
-    .with_fixes(fixes(&var_name, diagnostic_range, ast.file_id.is_macro()))
-    .experimental()
 }
 
 fn fixes(var_name: &String, diagnostic_range: FileRange, is_in_marco: bool) -> Option<Vec<Assist>> {
@@ -47,7 +53,7 @@ fn fixes(var_name: &String, diagnostic_range: FileRange, is_in_marco: bool) -> O
 
 #[cfg(test)]
 mod tests {
-    use crate::tests::{check_diagnostics, check_fix, check_no_fix};
+    use crate::tests::{check_diagnostics, check_fix};
 
     #[test]
     fn unused_variables_simple() {
@@ -193,7 +199,7 @@ fn main() {
 
     #[test]
     fn no_fix_for_marco() {
-        check_no_fix(
+        check_diagnostics(
             r#"
 macro_rules! my_macro {
     () => {
@@ -202,7 +208,7 @@ macro_rules! my_macro {
 }
 
 fn main() {
-    $0my_macro!();
+    my_macro!();
 }
 "#,
         );
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
index 0df6f0e0373..270cf844c65 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
@@ -330,7 +330,6 @@ pub fn diagnostics(
     }
 
     for diag in diags {
-        #[rustfmt::skip]
         let d = match diag {
             AnyDiagnostic::ExpectedFunction(d) => handlers::expected_function::expected_function(&ctx, &d),
             AnyDiagnostic::InactiveCode(d) => match handlers::inactive_code::inactive_code(&ctx, &d) {
@@ -361,7 +360,10 @@ pub fn diagnostics(
             AnyDiagnostic::MissingMatchArms(d) => handlers::missing_match_arms::missing_match_arms(&ctx, &d),
             AnyDiagnostic::MissingUnsafe(d) => handlers::missing_unsafe::missing_unsafe(&ctx, &d),
             AnyDiagnostic::MovedOutOfRef(d) => handlers::moved_out_of_ref::moved_out_of_ref(&ctx, &d),
-            AnyDiagnostic::NeedMut(d) => handlers::mutability_errors::need_mut(&ctx, &d),
+            AnyDiagnostic::NeedMut(d) => match handlers::mutability_errors::need_mut(&ctx, &d) {
+                Some(it) => it,
+                None => continue,
+            },
             AnyDiagnostic::NonExhaustiveLet(d) => handlers::non_exhaustive_let::non_exhaustive_let(&ctx, &d),
             AnyDiagnostic::NoSuchField(d) => handlers::no_such_field::no_such_field(&ctx, &d),
             AnyDiagnostic::PrivateAssocItem(d) => handlers::private_assoc_item::private_assoc_item(&ctx, &d),
@@ -385,12 +387,24 @@ pub fn diagnostics(
             AnyDiagnostic::UnresolvedMethodCall(d) => handlers::unresolved_method::unresolved_method(&ctx, &d),
             AnyDiagnostic::UnresolvedModule(d) => handlers::unresolved_module::unresolved_module(&ctx, &d),
             AnyDiagnostic::UnresolvedProcMacro(d) => handlers::unresolved_proc_macro::unresolved_proc_macro(&ctx, &d, config.proc_macros_enabled, config.proc_attr_macros_enabled),
-            AnyDiagnostic::UnusedMut(d) => handlers::mutability_errors::unused_mut(&ctx, &d),
-            AnyDiagnostic::UnusedVariable(d) => handlers::unused_variables::unused_variables(&ctx, &d),
+            AnyDiagnostic::UnusedMut(d) => match handlers::mutability_errors::unused_mut(&ctx, &d) {
+                Some(it) => it,
+                None => continue,
+            },
+            AnyDiagnostic::UnusedVariable(d) => match handlers::unused_variables::unused_variables(&ctx, &d) {
+                Some(it) => it,
+                None => continue,
+            },
             AnyDiagnostic::BreakOutsideOfLoop(d) => handlers::break_outside_of_loop::break_outside_of_loop(&ctx, &d),
             AnyDiagnostic::MismatchedTupleStructPatArgCount(d) => handlers::mismatched_arg_count::mismatched_tuple_struct_pat_arg_count(&ctx, &d),
-            AnyDiagnostic::RemoveTrailingReturn(d) => handlers::remove_trailing_return::remove_trailing_return(&ctx, &d),
-            AnyDiagnostic::RemoveUnnecessaryElse(d) => handlers::remove_unnecessary_else::remove_unnecessary_else(&ctx, &d),
+            AnyDiagnostic::RemoveTrailingReturn(d) => match handlers::remove_trailing_return::remove_trailing_return(&ctx, &d) {
+                Some(it) => it,
+                None => continue,
+            },
+            AnyDiagnostic::RemoveUnnecessaryElse(d) => match handlers::remove_unnecessary_else::remove_unnecessary_else(&ctx, &d) {
+                Some(it) => it,
+                None => continue,
+            },
         };
         res.push(d)
     }
@@ -399,9 +413,9 @@ pub fn diagnostics(
         .iter_mut()
         .filter_map(|it| {
             Some((
-                it.main_node
-                    .map(|ptr| ptr.map(|node| node.to_node(&ctx.sema.parse_or_expand(ptr.file_id))))
-                    .clone()?,
+                it.main_node.map(|ptr| {
+                    ptr.map(|node| node.to_node(&ctx.sema.parse_or_expand(ptr.file_id)))
+                })?,
                 it,
             ))
         })
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs
index dcaa2120892..bb5c2b79139 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs
@@ -283,6 +283,10 @@ fn test_disabled_diagnostics() {
 
 #[test]
 fn minicore_smoke_test() {
+    if test_utils::skip_slow_tests() {
+        return;
+    }
+
     fn check(minicore: MiniCore) {
         let source = minicore.source_code();
         let mut config = DiagnosticsConfig::test_sample();
diff --git a/src/tools/rust-analyzer/crates/ide/Cargo.toml b/src/tools/rust-analyzer/crates/ide/Cargo.toml
index aca7d613e11..a535015a27f 100644
--- a/src/tools/rust-analyzer/crates/ide/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide/Cargo.toml
@@ -36,6 +36,7 @@ ide-ssr.workspace = true
 profile.workspace = true
 stdx.workspace = true
 syntax.workspace = true
+span.workspace = true
 text-edit.workspace = true
 # ide should depend only on the top-level `hir` package. if you need
 # something from some `hir-xxx` subpackage, reexport the API via `hir`.
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 d10bdca50d8..64b4ccc5bd8 100644
--- a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
@@ -5,8 +5,6 @@ mod tests;
 
 mod intra_doc_links;
 
-use std::ffi::OsStr;
-
 use pulldown_cmark::{BrokenLink, CowStr, Event, InlineStr, LinkType, Options, Parser, Tag};
 use pulldown_cmark_to_cmark::{cmark_resume_with_options, Options as CMarkOptions};
 use stdx::format_to;
@@ -134,8 +132,8 @@ pub(crate) fn remove_links(markdown: &str) -> String {
 pub(crate) fn external_docs(
     db: &RootDatabase,
     FilePosition { file_id, offset }: FilePosition,
-    target_dir: Option<&OsStr>,
-    sysroot: Option<&OsStr>,
+    target_dir: Option<&str>,
+    sysroot: Option<&str>,
 ) -> Option<DocumentationLinks> {
     let sema = &Semantics::new(db);
     let file = sema.parse(file_id).syntax().clone();
@@ -331,8 +329,8 @@ fn broken_link_clone_cb(link: BrokenLink<'_>) -> Option<(CowStr<'_>, CowStr<'_>)
 fn get_doc_links(
     db: &RootDatabase,
     def: Definition,
-    target_dir: Option<&OsStr>,
-    sysroot: Option<&OsStr>,
+    target_dir: Option<&str>,
+    sysroot: Option<&str>,
 ) -> DocumentationLinks {
     let join_url = |base_url: Option<Url>, path: &str| -> Option<Url> {
         base_url.and_then(|url| url.join(path).ok())
@@ -479,15 +477,13 @@ fn map_links<'e>(
 fn get_doc_base_urls(
     db: &RootDatabase,
     def: Definition,
-    target_dir: Option<&OsStr>,
-    sysroot: Option<&OsStr>,
+    target_dir: Option<&str>,
+    sysroot: Option<&str>,
 ) -> (Option<Url>, Option<Url>) {
     let local_doc = target_dir
-        .and_then(|path| path.to_str())
         .and_then(|path| Url::parse(&format!("file:///{path}/")).ok())
         .and_then(|it| it.join("doc/").ok());
     let system_doc = sysroot
-        .and_then(|it| it.to_str())
         .map(|sysroot| format!("file:///{sysroot}/share/doc/rust/html/"))
         .and_then(|it| Url::parse(&it).ok());
 
diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs
index 60e8d29a716..ac44908a902 100644
--- a/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs
@@ -1,4 +1,4 @@
-use std::{ffi::OsStr, iter};
+use std::iter;
 
 use expect_test::{expect, Expect};
 use hir::Semantics;
@@ -18,10 +18,10 @@ use crate::{
 
 fn check_external_docs(
     ra_fixture: &str,
-    target_dir: Option<&OsStr>,
+    target_dir: Option<&str>,
     expect_web_url: Option<Expect>,
     expect_local_url: Option<Expect>,
-    sysroot: Option<&OsStr>,
+    sysroot: Option<&str>,
 ) {
     let (analysis, position) = fixture::position(ra_fixture);
     let links = analysis.external_docs(position, target_dir, sysroot).unwrap();
@@ -127,10 +127,10 @@ fn external_docs_doc_builtin_type() {
 //- /main.rs crate:foo
 let x: u3$02 = 0;
 "#,
-        Some(OsStr::new("/home/user/project")),
+        Some("/home/user/project"),
         Some(expect![[r#"https://doc.rust-lang.org/nightly/core/primitive.u32.html"#]]),
         Some(expect![[r#"file:///sysroot/share/doc/rust/html/core/primitive.u32.html"#]]),
-        Some(OsStr::new("/sysroot")),
+        Some("/sysroot"),
     );
 }
 
@@ -143,10 +143,10 @@ use foo$0::Foo;
 //- /lib.rs crate:foo
 pub struct Foo;
 "#,
-        Some(OsStr::new("/home/user/project")),
+        Some("/home/user/project"),
         Some(expect![[r#"https://docs.rs/foo/*/foo/index.html"#]]),
         Some(expect![[r#"file:///home/user/project/doc/foo/index.html"#]]),
-        Some(OsStr::new("/sysroot")),
+        Some("/sysroot"),
     );
 }
 
@@ -157,10 +157,10 @@ fn external_docs_doc_url_std_crate() {
 //- /main.rs crate:std
 use self$0;
 "#,
-        Some(OsStr::new("/home/user/project")),
+        Some("/home/user/project"),
         Some(expect!["https://doc.rust-lang.org/stable/std/index.html"]),
         Some(expect!["file:///sysroot/share/doc/rust/html/std/index.html"]),
-        Some(OsStr::new("/sysroot")),
+        Some("/sysroot"),
     );
 }
 
@@ -171,10 +171,10 @@ fn external_docs_doc_url_struct() {
 //- /main.rs crate:foo
 pub struct Fo$0o;
 "#,
-        Some(OsStr::new("/home/user/project")),
+        Some("/home/user/project"),
         Some(expect![[r#"https://docs.rs/foo/*/foo/struct.Foo.html"#]]),
         Some(expect![[r#"file:///home/user/project/doc/foo/struct.Foo.html"#]]),
-        Some(OsStr::new("/sysroot")),
+        Some("/sysroot"),
     );
 }
 
@@ -185,10 +185,10 @@ fn external_docs_doc_url_windows_backslash_path() {
 //- /main.rs crate:foo
 pub struct Fo$0o;
 "#,
-        Some(OsStr::new(r"C:\Users\user\project")),
+        Some(r"C:\Users\user\project"),
         Some(expect![[r#"https://docs.rs/foo/*/foo/struct.Foo.html"#]]),
         Some(expect![[r#"file:///C:/Users/user/project/doc/foo/struct.Foo.html"#]]),
-        Some(OsStr::new("/sysroot")),
+        Some("/sysroot"),
     );
 }
 
@@ -199,10 +199,10 @@ fn external_docs_doc_url_windows_slash_path() {
 //- /main.rs crate:foo
 pub struct Fo$0o;
 "#,
-        Some(OsStr::new(r"C:/Users/user/project")),
+        Some("C:/Users/user/project"),
         Some(expect![[r#"https://docs.rs/foo/*/foo/struct.Foo.html"#]]),
         Some(expect![[r#"file:///C:/Users/user/project/doc/foo/struct.Foo.html"#]]),
-        Some(OsStr::new("/sysroot")),
+        Some("/sysroot"),
     );
 }
 
diff --git a/src/tools/rust-analyzer/crates/ide/src/file_structure.rs b/src/tools/rust-analyzer/crates/ide/src/file_structure.rs
index 0e790e14205..813691540f9 100644
--- a/src/tools/rust-analyzer/crates/ide/src/file_structure.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/file_structure.rs
@@ -134,15 +134,22 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
                 if let Some(type_param_list) = it.generic_param_list() {
                     collapse_ws(type_param_list.syntax(), &mut detail);
                 }
-                if let Some(param_list) = it.param_list() {
+                let has_self_param = if let Some(param_list) = it.param_list() {
                     collapse_ws(param_list.syntax(), &mut detail);
-                }
+                    param_list.self_param().is_some()
+                } else {
+                    false
+                };
                 if let Some(ret_type) = it.ret_type() {
                     detail.push(' ');
                     collapse_ws(ret_type.syntax(), &mut detail);
                 }
 
-                decl_with_detail(&it, Some(detail), StructureNodeKind::SymbolKind(SymbolKind::Function))
+                decl_with_detail(&it, Some(detail), StructureNodeKind::SymbolKind(if has_self_param {
+                    SymbolKind::Method
+                } else {
+                    SymbolKind::Function
+                }))
             },
             ast::Struct(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Struct)),
             ast::Union(it) => decl(it, StructureNodeKind::SymbolKind(SymbolKind::Union)),
diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs b/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs
index 8a12cbacccc..76e5e9dd928 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs
@@ -340,4 +340,75 @@ impl Tr for S {
 "#,
         );
     }
+
+    #[test]
+    fn goto_adt_implementation_inside_block() {
+        check(
+            r#"
+//- minicore: copy, derive
+trait Bar {}
+
+fn test() {
+    #[derive(Copy)]
+  //^^^^^^^^^^^^^^^
+    struct Foo$0;
+
+    impl Foo {}
+       //^^^
+
+    trait Baz {}
+
+    impl Bar for Foo {}
+               //^^^
+
+    impl Baz for Foo {}
+               //^^^
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn goto_trait_implementation_inside_block() {
+        check(
+            r#"
+struct Bar;
+
+fn test() {
+    trait Foo$0 {}
+
+    struct Baz;
+
+    impl Foo for Bar {}
+               //^^^
+
+    impl Foo for Baz {}
+               //^^^
+}
+"#,
+        );
+        check(
+            r#"
+struct Bar;
+
+fn test() {
+    trait Foo {
+        fn foo$0() {}
+    }
+
+    struct Baz;
+
+    impl Foo for Bar {
+        fn foo() {}
+         //^^^
+    }
+
+    impl Foo for Baz {
+        fn foo() {}
+         //^^^
+    }
+}
+"#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs
index 8f4c629b581..822751c0e4c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs
@@ -33,6 +33,7 @@ pub struct HoverConfig {
     pub keywords: bool,
     pub format: HoverDocFormat,
     pub max_trait_assoc_items_count: Option<usize>,
+    pub max_struct_field_count: Option<usize>,
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
index 63777d49105..abedbff831a 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
@@ -410,6 +410,9 @@ pub(super) fn definition(
         Definition::Trait(trait_) => {
             trait_.display_limited(db, config.max_trait_assoc_items_count).to_string()
         }
+        Definition::Adt(Adt::Struct(struct_)) => {
+            struct_.display_limited(db, config.max_struct_field_count).to_string()
+        }
         _ => def.label(db),
     };
     let docs = def.docs(db, famous_defs);
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
index 4451e31870f..08925fcdff5 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
@@ -18,6 +18,7 @@ const HOVER_BASE_CONFIG: HoverConfig = HoverConfig {
     format: HoverDocFormat::Markdown,
     keywords: true,
     max_trait_assoc_items_count: None,
+    max_struct_field_count: None,
 };
 
 fn check_hover_no_result(ra_fixture: &str) {
@@ -50,6 +51,28 @@ fn check(ra_fixture: &str, expect: Expect) {
 }
 
 #[track_caller]
+fn check_hover_struct_limit(count: usize, ra_fixture: &str, expect: Expect) {
+    let (analysis, position) = fixture::position(ra_fixture);
+    let hover = analysis
+        .hover(
+            &HoverConfig {
+                links_in_hover: true,
+                max_struct_field_count: Some(count),
+                ..HOVER_BASE_CONFIG
+            },
+            FileRange { file_id: position.file_id, range: TextRange::empty(position.offset) },
+        )
+        .unwrap()
+        .unwrap();
+
+    let content = analysis.db.file_text(position.file_id);
+    let hovered_element = &content[hover.range];
+
+    let actual = format!("*{hovered_element}*\n{}\n", hover.info.markup);
+    expect.assert_eq(&actual)
+}
+
+#[track_caller]
 fn check_assoc_count(count: usize, ra_fixture: &str, expect: Expect) {
     let (analysis, position) = fixture::position(ra_fixture);
     let hover = analysis
@@ -853,9 +876,7 @@ struct Foo$0 { field: u32 }
 
             ```rust
             // size = 4, align = 4
-            struct Foo {
-                field: u32,
-            }
+            struct Foo
             ```
         "#]],
     );
@@ -875,8 +896,74 @@ struct Foo$0 where u32: Copy { field: u32 }
             struct Foo
             where
                 u32: Copy,
-            {
-                field: u32,
+            ```
+        "#]],
+    );
+}
+
+#[test]
+fn hover_record_struct_limit() {
+    check_hover_struct_limit(
+        3,
+        r#"
+    struct Foo$0 { a: u32, b: i32, c: i32 }
+    "#,
+        expect![[r#"
+            *Foo*
+
+            ```rust
+            test
+            ```
+
+            ```rust
+            // size = 12 (0xC), align = 4
+            struct Foo  {
+                a: u32,
+                b: i32,
+                c: i32,
+            }
+            ```
+        "#]],
+    );
+    check_hover_struct_limit(
+        3,
+        r#"
+    struct Foo$0 { a: u32 }
+    "#,
+        expect![[r#"
+            *Foo*
+
+            ```rust
+            test
+            ```
+
+            ```rust
+            // size = 4, align = 4
+            struct Foo  {
+                a: u32,
+            }
+            ```
+        "#]],
+    );
+    check_hover_struct_limit(
+        3,
+        r#"
+    struct Foo$0 { a: u32, b: i32, c: i32, d: u32 }
+    "#,
+        expect![[r#"
+            *Foo*
+
+            ```rust
+            test
+            ```
+
+            ```rust
+            // size = 16 (0x10), align = 4
+            struct Foo  {
+                a: u32,
+                b: i32,
+                c: i32,
+                /* … */
             }
             ```
         "#]],
@@ -1344,9 +1431,7 @@ impl Thing {
                 ```
 
                 ```rust
-                struct Thing {
-                    x: u32,
-                }
+                struct Thing
                 ```
             "#]],
     );
@@ -1365,9 +1450,7 @@ impl Thing {
                 ```
 
                 ```rust
-                struct Thing {
-                    x: u32,
-                }
+                struct Thing
                 ```
             "#]],
     );
@@ -2599,7 +2682,7 @@ fn main() { let s$0t = S{ f1:0 }; }
                                     focus_range: 7..8,
                                     name: "S",
                                     kind: Struct,
-                                    description: "struct S {\n    f1: u32,\n}",
+                                    description: "struct S",
                                 },
                             },
                         ],
@@ -2645,7 +2728,7 @@ fn main() { let s$0t = S{ f1:Arg(0) }; }
                                 focus_range: 24..25,
                                 name: "S",
                                 kind: Struct,
-                                description: "struct S<T> {\n    f1: T,\n}",
+                                description: "struct S<T>",
                             },
                         },
                     ],
@@ -2704,7 +2787,7 @@ fn main() { let s$0t = S{ f1: S{ f1: Arg(0) } }; }
                                 focus_range: 24..25,
                                 name: "S",
                                 kind: Struct,
-                                description: "struct S<T> {\n    f1: T,\n}",
+                                description: "struct S<T>",
                             },
                         },
                     ],
@@ -2957,7 +3040,7 @@ fn main() { let s$0t = foo(); }
                                 focus_range: 39..41,
                                 name: "S1",
                                 kind: Struct,
-                                description: "struct S1 {}",
+                                description: "struct S1",
                             },
                         },
                         HoverGotoTypeData {
@@ -2970,7 +3053,7 @@ fn main() { let s$0t = foo(); }
                                 focus_range: 52..54,
                                 name: "S2",
                                 kind: Struct,
-                                description: "struct S2 {}",
+                                description: "struct S2",
                             },
                         },
                     ],
@@ -3061,7 +3144,7 @@ fn foo(ar$0g: &impl Foo + Bar<S>) {}
                                 focus_range: 36..37,
                                 name: "S",
                                 kind: Struct,
-                                description: "struct S {}",
+                                description: "struct S",
                             },
                         },
                     ],
@@ -3161,7 +3244,7 @@ fn foo(ar$0g: &impl Foo<S>) {}
                                 focus_range: 23..24,
                                 name: "S",
                                 kind: Struct,
-                                description: "struct S {}",
+                                description: "struct S",
                             },
                         },
                     ],
@@ -3198,7 +3281,7 @@ fn main() { let s$0t = foo(); }
                                 focus_range: 49..50,
                                 name: "B",
                                 kind: Struct,
-                                description: "struct B<T> {}",
+                                description: "struct B<T>",
                             },
                         },
                         HoverGotoTypeData {
@@ -3287,7 +3370,7 @@ fn foo(ar$0g: &dyn Foo<S>) {}
                                 focus_range: 23..24,
                                 name: "S",
                                 kind: Struct,
-                                description: "struct S {}",
+                                description: "struct S",
                             },
                         },
                     ],
@@ -3322,7 +3405,7 @@ fn foo(a$0rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
                                 focus_range: 50..51,
                                 name: "B",
                                 kind: Struct,
-                                description: "struct B<T> {}",
+                                description: "struct B<T>",
                             },
                         },
                         HoverGotoTypeData {
@@ -3361,7 +3444,7 @@ fn foo(a$0rg: &impl ImplTrait<B<dyn DynTrait<B<S>>>>) {}
                                 focus_range: 65..66,
                                 name: "S",
                                 kind: Struct,
-                                description: "struct S {}",
+                                description: "struct S",
                             },
                         },
                     ],
@@ -5106,6 +5189,32 @@ fn foo(e: E) {
 }
 
 #[test]
+fn hover_const_value() {
+    check(
+        r#"
+pub enum AA {
+    BB,
+}
+const CONST: AA = AA::BB;
+pub fn the_function() -> AA {
+    CON$0ST
+}
+"#,
+        expect![[r#"
+            *CONST*
+
+            ```rust
+            test
+            ```
+
+            ```rust
+            const CONST: AA = BB
+            ```
+        "#]],
+    );
+}
+
+#[test]
 fn array_repeat_exp() {
     check(
         r#"
@@ -7747,3 +7856,25 @@ impl Iterator for S {
         "#]],
     );
 }
+
+#[test]
+fn hover_lifetime_regression_16963() {
+    check(
+        r#"
+struct Pedro$0<'a> {
+    hola: &'a str
+}
+"#,
+        expect![[r#"
+            *Pedro*
+
+            ```rust
+            test
+            ```
+
+            ```rust
+            struct Pedro<'a>
+            ```
+        "#]],
+    )
+}
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
index 8311e770b4b..dda38ce77e0 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
@@ -1,5 +1,6 @@
 use std::{
     fmt::{self, Write},
+    hash::{BuildHasher, BuildHasherDefault},
     mem::take,
 };
 
@@ -8,7 +9,7 @@ use hir::{
     known, ClosureStyle, HasVisibility, HirDisplay, HirDisplayError, HirWrite, ModuleDef,
     ModuleDefId, Semantics,
 };
-use ide_db::{base_db::FileRange, famous_defs::FamousDefs, RootDatabase};
+use ide_db::{base_db::FileRange, famous_defs::FamousDefs, FxHasher, RootDatabase};
 use itertools::Itertools;
 use smallvec::{smallvec, SmallVec};
 use stdx::never;
@@ -116,7 +117,7 @@ pub enum AdjustmentHintsMode {
     PreferPostfix,
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub enum InlayKind {
     Adjustment,
     BindingMode,
@@ -132,7 +133,7 @@ pub enum InlayKind {
     RangeExclusive,
 }
 
-#[derive(Debug)]
+#[derive(Debug, Hash)]
 pub enum InlayHintPosition {
     Before,
     After,
@@ -151,13 +152,23 @@ pub struct InlayHint {
     pub label: InlayHintLabel,
     /// Text edit to apply when "accepting" this inlay hint.
     pub text_edit: Option<TextEdit>,
-    pub needs_resolve: bool,
+}
+
+impl std::hash::Hash for InlayHint {
+    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+        self.range.hash(state);
+        self.position.hash(state);
+        self.pad_left.hash(state);
+        self.pad_right.hash(state);
+        self.kind.hash(state);
+        self.label.hash(state);
+        self.text_edit.is_some().hash(state);
+    }
 }
 
 impl InlayHint {
     fn closing_paren_after(kind: InlayKind, range: TextRange) -> InlayHint {
         InlayHint {
-            needs_resolve: false,
             range,
             kind,
             label: InlayHintLabel::from(")"),
@@ -167,9 +178,9 @@ impl InlayHint {
             pad_right: false,
         }
     }
+
     fn opening_paren_before(kind: InlayKind, range: TextRange) -> InlayHint {
         InlayHint {
-            needs_resolve: false,
             range,
             kind,
             label: InlayHintLabel::from("("),
@@ -179,15 +190,19 @@ impl InlayHint {
             pad_right: false,
         }
     }
+
+    pub fn needs_resolve(&self) -> bool {
+        self.text_edit.is_some() || self.label.needs_resolve()
+    }
 }
 
-#[derive(Debug)]
+#[derive(Debug, Hash)]
 pub enum InlayTooltip {
     String(String),
     Markdown(String),
 }
 
-#[derive(Default)]
+#[derive(Default, Hash)]
 pub struct InlayHintLabel {
     pub parts: SmallVec<[InlayHintLabelPart; 1]>,
 }
@@ -265,6 +280,7 @@ impl fmt::Debug for InlayHintLabel {
     }
 }
 
+#[derive(Hash)]
 pub struct InlayHintLabelPart {
     pub text: String,
     /// Source location represented by this label part. The client will use this to fetch the part's
@@ -313,9 +329,7 @@ impl fmt::Write for InlayHintLabelBuilder<'_> {
 
 impl HirWrite for InlayHintLabelBuilder<'_> {
     fn start_location_link(&mut self, def: ModuleDefId) {
-        if self.location.is_some() {
-            never!("location link is already started");
-        }
+        never!(self.location.is_some(), "location link is already started");
         self.make_new_part();
         let Some(location) = ModuleDef::from(def).try_to_nav(self.db) else { return };
         let location = location.call_site();
@@ -425,11 +439,6 @@ fn ty_to_text_edit(
     Some(builder.finish())
 }
 
-pub enum RangeLimit {
-    Fixed(TextRange),
-    NearestParent(TextSize),
-}
-
 // Feature: Inlay Hints
 //
 // rust-analyzer shows additional information inline with the source code.
@@ -451,7 +460,7 @@ pub enum RangeLimit {
 pub(crate) fn inlay_hints(
     db: &RootDatabase,
     file_id: FileId,
-    range_limit: Option<RangeLimit>,
+    range_limit: Option<TextRange>,
     config: &InlayHintsConfig,
 ) -> Vec<InlayHint> {
     let _p = tracing::span!(tracing::Level::INFO, "inlay_hints").entered();
@@ -466,31 +475,13 @@ pub(crate) fn inlay_hints(
 
         let hints = |node| hints(&mut acc, &famous_defs, config, file_id, node);
         match range_limit {
-            Some(RangeLimit::Fixed(range)) => match file.covering_element(range) {
+            Some(range) => match file.covering_element(range) {
                 NodeOrToken::Token(_) => return acc,
                 NodeOrToken::Node(n) => n
                     .descendants()
                     .filter(|descendant| range.intersect(descendant.text_range()).is_some())
                     .for_each(hints),
             },
-            Some(RangeLimit::NearestParent(position)) => {
-                match file.token_at_offset(position).left_biased() {
-                    Some(token) => {
-                        if let Some(parent_block) =
-                            token.parent_ancestors().find_map(ast::BlockExpr::cast)
-                        {
-                            parent_block.syntax().descendants().for_each(hints)
-                        } else if let Some(parent_item) =
-                            token.parent_ancestors().find_map(ast::Item::cast)
-                        {
-                            parent_item.syntax().descendants().for_each(hints)
-                        } else {
-                            return acc;
-                        }
-                    }
-                    None => return acc,
-                }
-            }
             None => file.descendants().for_each(hints),
         };
     }
@@ -498,6 +489,39 @@ pub(crate) fn inlay_hints(
     acc
 }
 
+pub(crate) fn inlay_hints_resolve(
+    db: &RootDatabase,
+    file_id: FileId,
+    position: TextSize,
+    hash: u64,
+    config: &InlayHintsConfig,
+) -> Option<InlayHint> {
+    let _p = tracing::span!(tracing::Level::INFO, "inlay_hints").entered();
+    let sema = Semantics::new(db);
+    let file = sema.parse(file_id);
+    let file = file.syntax();
+
+    let scope = sema.scope(file)?;
+    let famous_defs = FamousDefs(&sema, scope.krate());
+    let mut acc = Vec::new();
+
+    let hints = |node| hints(&mut acc, &famous_defs, config, file_id, node);
+    match file.token_at_offset(position).left_biased() {
+        Some(token) => {
+            if let Some(parent_block) = token.parent_ancestors().find_map(ast::BlockExpr::cast) {
+                parent_block.syntax().descendants().for_each(hints)
+            } else if let Some(parent_item) = token.parent_ancestors().find_map(ast::Item::cast) {
+                parent_item.syntax().descendants().for_each(hints)
+            } else {
+                return None;
+            }
+        }
+        None => return None,
+    }
+
+    acc.into_iter().find(|hint| BuildHasherDefault::<FxHasher>::default().hash_one(hint) == hash)
+}
+
 fn hints(
     hints: &mut Vec<InlayHint>,
     famous_defs @ FamousDefs(sema, _): &FamousDefs<'_, '_>,
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs
index 631807d99a7..20128a286f2 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs
@@ -147,7 +147,6 @@ pub(super) fn hints(
             None,
         );
         acc.push(InlayHint {
-            needs_resolve: label.needs_resolve(),
             range: expr.syntax().text_range(),
             pad_left: false,
             pad_right: false,
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs
index 45b51e35570..07b9f9cc1ff 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/bind_pat.rs
@@ -99,7 +99,6 @@ pub(super) fn hints(
         None => pat.syntax().text_range(),
     };
     acc.push(InlayHint {
-        needs_resolve: label.needs_resolve() || text_edit.is_some(),
         range: match type_ascriptable {
             Some(Some(t)) => text_range.cover(t.text_range()),
             _ => text_range,
@@ -177,11 +176,7 @@ mod tests {
     use syntax::{TextRange, TextSize};
     use test_utils::extract_annotations;
 
-    use crate::{
-        fixture,
-        inlay_hints::{InlayHintsConfig, RangeLimit},
-        ClosureReturnTypeHints,
-    };
+    use crate::{fixture, inlay_hints::InlayHintsConfig, ClosureReturnTypeHints};
 
     use crate::inlay_hints::tests::{
         check, check_edit, check_no_edit, check_with_config, DISABLED_CONFIG, TEST_CONFIG,
@@ -404,7 +399,7 @@ fn main() {
             .inlay_hints(
                 &InlayHintsConfig { type_hints: true, ..DISABLED_CONFIG },
                 file_id,
-                Some(RangeLimit::Fixed(TextRange::new(TextSize::from(500), TextSize::from(600)))),
+                Some(TextRange::new(TextSize::from(500), TextSize::from(600))),
             )
             .unwrap();
         let actual =
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs
index 35504ffa785..f27390ee898 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs
@@ -50,7 +50,6 @@ pub(super) fn hints(
             _ => return,
         };
         acc.push(InlayHint {
-            needs_resolve: false,
             range,
             kind: InlayKind::BindingMode,
             label: r.into(),
@@ -69,7 +68,6 @@ pub(super) fn hints(
                 hir::BindingMode::Ref(Mutability::Shared) => "ref",
             };
             acc.push(InlayHint {
-                needs_resolve: false,
                 range: pat.syntax().text_range(),
                 kind: InlayKind::BindingMode,
                 label: bm.into(),
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs
index b6063978e92..d86487d4b41 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/chaining.rs
@@ -59,7 +59,6 @@ pub(super) fn hints(
             }
             let label = label_of_ty(famous_defs, config, &ty)?;
             acc.push(InlayHint {
-                needs_resolve: label.needs_resolve(),
                 range: expr.syntax().text_range(),
                 kind: InlayKind::Chaining,
                 label,
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs
index 2b68538c198..2cefd5acdc2 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closing_brace.rs
@@ -109,7 +109,6 @@ pub(super) fn hints(
 
     let linked_location = name_range.map(|range| FileRange { file_id, range });
     acc.push(InlayHint {
-        needs_resolve: linked_location.is_some(),
         range: closing_token.text_range(),
         kind: InlayKind::ClosingBrace,
         label: InlayHintLabel::simple(label, None, linked_location),
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_captures.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_captures.rs
index 2f8b959516d..f1b524e0880 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_captures.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_captures.rs
@@ -32,7 +32,6 @@ pub(super) fn hints(
             let range = closure.syntax().first_token()?.prev_token()?.text_range();
             let range = TextRange::new(range.end() - TextSize::from(1), range.end());
             acc.push(InlayHint {
-                needs_resolve: false,
                 range,
                 kind: InlayKind::ClosureCapture,
                 label: InlayHintLabel::from("move"),
@@ -45,7 +44,6 @@ pub(super) fn hints(
         }
     };
     acc.push(InlayHint {
-        needs_resolve: false,
         range: move_kw_range,
         kind: InlayKind::ClosureCapture,
         label: InlayHintLabel::from("("),
@@ -79,7 +77,6 @@ pub(super) fn hints(
             }),
         );
         acc.push(InlayHint {
-            needs_resolve: label.needs_resolve(),
             range: move_kw_range,
             kind: InlayKind::ClosureCapture,
             label,
@@ -91,7 +88,6 @@ pub(super) fn hints(
 
         if idx != last {
             acc.push(InlayHint {
-                needs_resolve: false,
                 range: move_kw_range,
                 kind: InlayKind::ClosureCapture,
                 label: InlayHintLabel::from(", "),
@@ -103,7 +99,6 @@ pub(super) fn hints(
         }
     }
     acc.push(InlayHint {
-        needs_resolve: false,
         range: move_kw_range,
         kind: InlayKind::ClosureCapture,
         label: InlayHintLabel::from(")"),
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs
index 204967cd7ca..3b41db0f13d 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/closure_ret.rs
@@ -64,7 +64,6 @@ pub(super) fn hints(
     };
 
     acc.push(InlayHint {
-        needs_resolve: label.needs_resolve() || text_edit.is_some(),
         range: param_list.syntax().text_range(),
         kind: InlayKind::Type,
         label,
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs
index 06cce147d2a..202954100fb 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs
@@ -79,7 +79,6 @@ fn variant_hints(
         None,
     );
     acc.push(InlayHint {
-        needs_resolve: label.needs_resolve(),
         range: match eq_token {
             Some(t) => range.cover(t.text_range()),
             _ => range,
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/fn_lifetime_fn.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/fn_lifetime_fn.rs
index 6e5f23bed09..d3666754e2b 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/fn_lifetime_fn.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/fn_lifetime_fn.rs
@@ -22,7 +22,6 @@ pub(super) fn hints(
     }
 
     let mk_lt_hint = |t: SyntaxToken, label: String| InlayHint {
-        needs_resolve: false,
         range: t.text_range(),
         kind: InlayKind::Lifetime,
         label: label.into(),
@@ -184,7 +183,6 @@ pub(super) fn hints(
             let angle_tok = gpl.l_angle_token()?;
             let is_empty = gpl.generic_params().next().is_none();
             acc.push(InlayHint {
-                needs_resolve: false,
                 range: angle_tok.text_range(),
                 kind: InlayKind::Lifetime,
                 label: format!(
@@ -200,7 +198,6 @@ pub(super) fn hints(
             });
         }
         (None, allocated_lifetimes) => acc.push(InlayHint {
-            needs_resolve: false,
             range: func.name()?.syntax().text_range(),
             kind: InlayKind::GenericParamList,
             label: format!("<{}>", allocated_lifetimes.iter().format(", "),).into(),
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs
index 5ba4e514e1f..31f0c790374 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_drop.rs
@@ -105,7 +105,6 @@ pub(super) fn hints(
                 pad_left: true,
                 pad_right: true,
                 kind: InlayKind::Drop,
-                needs_resolve: label.needs_resolve(),
                 label,
                 text_edit: None,
             })
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs
index f18e6421cbc..42223ddf580 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/implicit_static.rs
@@ -31,7 +31,6 @@ pub(super) fn hints(
         if ty.lifetime().is_none() {
             let t = ty.amp_token()?;
             acc.push(InlayHint {
-                needs_resolve: false,
                 range: t.text_range(),
                 kind: InlayKind::Lifetime,
                 label: "'static".into(),
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs
index 418fc002a8b..96e845b2f32 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs
@@ -57,7 +57,6 @@ pub(super) fn hints(
             let label =
                 InlayHintLabel::simple(format!("{param_name}{colon}"), None, linked_location);
             InlayHint {
-                needs_resolve: label.needs_resolve(),
                 range,
                 kind: InlayKind::Parameter,
                 label,
diff --git a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/range_exclusive.rs b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/range_exclusive.rs
index c4b0c199fc2..bfb92838857 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints/range_exclusive.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints/range_exclusive.rs
@@ -30,7 +30,6 @@ fn inlay_hint(token: SyntaxToken) -> InlayHint {
         kind: crate::InlayKind::RangeExclusive,
         label: crate::InlayHintLabel::from("<"),
         text_edit: None,
-        needs_resolve: false,
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs
index 6955e14a10a..ad48d803895 100644
--- a/src/tools/rust-analyzer/crates/ide/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs
@@ -58,8 +58,6 @@ mod view_item_tree;
 mod view_memory_layout;
 mod view_mir;
 
-use std::ffi::OsStr;
-
 use cfg::CfgOptions;
 use fetch_crates::CrateInfo;
 use hir::ChangeWithProcMacros;
@@ -90,7 +88,7 @@ pub use crate::{
     inlay_hints::{
         AdjustmentHints, AdjustmentHintsMode, ClosureReturnTypeHints, DiscriminantHints,
         InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart, InlayHintPosition,
-        InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints, RangeLimit,
+        InlayHintsConfig, InlayKind, InlayTooltip, LifetimeElisionHints,
     },
     join_lines::JoinLinesConfig,
     markup::Markup,
@@ -121,8 +119,8 @@ pub use ide_completion::{
 };
 pub use ide_db::{
     base_db::{
-        Cancelled, CrateGraph, CrateId, Edition, FileChange, FileId, FilePosition, FileRange,
-        SourceRoot, SourceRootId,
+        Cancelled, CrateGraph, CrateId, FileChange, FileId, FilePosition, FileRange, SourceRoot,
+        SourceRootId,
     },
     documentation::Documentation,
     label::Label,
@@ -137,6 +135,7 @@ pub use ide_diagnostics::{
     Diagnostic, DiagnosticCode, DiagnosticsConfig, ExprFillDefaultMode, Severity,
 };
 pub use ide_ssr::SsrError;
+pub use span::Edition;
 pub use syntax::{TextRange, TextSize};
 pub use text_edit::{Indel, TextEdit};
 
@@ -354,6 +353,10 @@ impl Analysis {
         self.with_db(|db| test_explorer::discover_tests_in_crate(db, crate_id))
     }
 
+    pub fn discover_tests_in_file(&self, file_id: FileId) -> Cancellable<Vec<TestItem>> {
+        self.with_db(|db| test_explorer::discover_tests_in_file(db, file_id))
+    }
+
     /// Renders the crate graph to GraphViz "dot" syntax.
     pub fn view_crate_graph(&self, full: bool) -> Cancellable<Result<String, String>> {
         self.with_db(|db| view_crate_graph::view_crate_graph(db, full))
@@ -415,10 +418,19 @@ impl Analysis {
         &self,
         config: &InlayHintsConfig,
         file_id: FileId,
-        range: Option<RangeLimit>,
+        range: Option<TextRange>,
     ) -> Cancellable<Vec<InlayHint>> {
         self.with_db(|db| inlay_hints::inlay_hints(db, file_id, range, config))
     }
+    pub fn inlay_hints_resolve(
+        &self,
+        config: &InlayHintsConfig,
+        file_id: FileId,
+        position: TextSize,
+        hash: u64,
+    ) -> Cancellable<Option<InlayHint>> {
+        self.with_db(|db| inlay_hints::inlay_hints_resolve(db, file_id, position, hash, config))
+    }
 
     /// Returns the set of folding ranges.
     pub fn folding_ranges(&self, file_id: FileId) -> Cancellable<Vec<Fold>> {
@@ -502,8 +514,8 @@ impl Analysis {
     pub fn external_docs(
         &self,
         position: FilePosition,
-        target_dir: Option<&OsStr>,
-        sysroot: Option<&OsStr>,
+        target_dir: Option<&str>,
+        sysroot: Option<&str>,
     ) -> Cancellable<doc_links::DocumentationLinks> {
         self.with_db(|db| {
             doc_links::external_docs(db, position, target_dir, sysroot).unwrap_or_default()
diff --git a/src/tools/rust-analyzer/crates/ide/src/static_index.rs b/src/tools/rust-analyzer/crates/ide/src/static_index.rs
index fe063081f79..3fef16df25e 100644
--- a/src/tools/rust-analyzer/crates/ide/src/static_index.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/static_index.rs
@@ -167,6 +167,7 @@ impl StaticIndex<'_> {
             keywords: true,
             format: crate::HoverDocFormat::Markdown,
             max_trait_assoc_items_count: None,
+            max_struct_field_count: None,
         };
         let tokens = tokens.filter(|token| {
             matches!(
diff --git a/src/tools/rust-analyzer/crates/ide/src/status.rs b/src/tools/rust-analyzer/crates/ide/src/status.rs
index c3d85e38936..8e7767c8e5d 100644
--- a/src/tools/rust-analyzer/crates/ide/src/status.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/status.rs
@@ -10,7 +10,7 @@ use ide_db::{
             debug::{DebugQueryTable, TableEntry},
             Query, QueryTable,
         },
-        CrateData, FileId, FileTextQuery, ParseQuery, SourceDatabase, SourceRootId,
+        CompressedFileTextQuery, CrateData, FileId, ParseQuery, SourceDatabase, SourceRootId,
     },
     symbol_index::ModuleSymbolsQuery,
 };
@@ -38,7 +38,7 @@ use triomphe::Arc;
 pub(crate) fn status(db: &RootDatabase, file_id: Option<FileId>) -> String {
     let mut buf = String::new();
 
-    format_to!(buf, "{}\n", collect_query(FileTextQuery.in_db(db)));
+    format_to!(buf, "{}\n", collect_query(CompressedFileTextQuery.in_db(db)));
     format_to!(buf, "{}\n", collect_query(ParseQuery.in_db(db)));
     format_to!(buf, "{}\n", collect_query(ParseMacroExpansionQuery.in_db(db)));
     format_to!(buf, "{}\n", collect_query(LibrarySymbolsQuery.in_db(db)));
@@ -160,7 +160,7 @@ impl QueryCollect for ParseMacroExpansionQuery {
     type Collector = SyntaxTreeStats<true>;
 }
 
-impl QueryCollect for FileTextQuery {
+impl QueryCollect for CompressedFileTextQuery {
     type Collector = FilesStats;
 }
 
@@ -188,8 +188,8 @@ impl fmt::Display for FilesStats {
     }
 }
 
-impl StatCollect<FileId, Arc<str>> for FilesStats {
-    fn collect_entry(&mut self, _: FileId, value: Option<Arc<str>>) {
+impl StatCollect<FileId, Arc<[u8]>> for FilesStats {
+    fn collect_entry(&mut self, _: FileId, value: Option<Arc<[u8]>>) {
         self.total += 1;
         self.size += value.unwrap().len();
     }
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs
index 96c7c475594..e7346cbb992 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs
@@ -178,6 +178,23 @@ fn keyword(
         T![do] | T![yeet] if parent_matches::<ast::YeetExpr>(&token) => h | HlMod::ControlFlow,
         T![for] if parent_matches::<ast::ForExpr>(&token) => h | HlMod::ControlFlow,
         T![unsafe] => h | HlMod::Unsafe,
+        T![const]
+            if token.parent().map_or(false, |it| {
+                matches!(
+                    it.kind(),
+                    SyntaxKind::CONST
+                        | SyntaxKind::FN
+                        | SyntaxKind::IMPL
+                        | SyntaxKind::BLOCK_EXPR
+                        | SyntaxKind::CLOSURE_EXPR
+                        | SyntaxKind::FN_PTR_TYPE
+                        | SyntaxKind::TYPE_BOUND
+                        | SyntaxKind::CONST_BLOCK_PAT
+                )
+            }) =>
+        {
+            h | HlMod::Const
+        }
         T![true] | T![false] => HlTag::BoolLiteral.into(),
         // crate is handled just as a token if it's in an `extern crate`
         T![crate] if parent_matches::<ast::ExternCrate>(&token) => h,
@@ -377,14 +394,17 @@ pub(super) fn highlight_def(
             if let Some(item) = func.as_assoc_item(db) {
                 h |= HlMod::Associated;
                 match func.self_param(db) {
-                    Some(sp) => match sp.access(db) {
-                        hir::Access::Exclusive => {
-                            h |= HlMod::Mutable;
-                            h |= HlMod::Reference;
+                    Some(sp) => {
+                        h.tag = HlTag::Symbol(SymbolKind::Method);
+                        match sp.access(db) {
+                            hir::Access::Exclusive => {
+                                h |= HlMod::Mutable;
+                                h |= HlMod::Reference;
+                            }
+                            hir::Access::Shared => h |= HlMod::Reference,
+                            hir::Access::Owned => h |= HlMod::Consuming,
                         }
-                        hir::Access::Shared => h |= HlMod::Reference,
-                        hir::Access::Owned => h |= HlMod::Consuming,
-                    },
+                    }
                     None => h |= HlMod::Static,
                 }
 
@@ -406,6 +426,9 @@ pub(super) fn highlight_def(
             if func.is_async(db) {
                 h |= HlMod::Async;
             }
+            if func.is_const(db) {
+                h |= HlMod::Const;
+            }
 
             h
         }
@@ -420,10 +443,11 @@ pub(super) fn highlight_def(
         }
         Definition::Variant(_) => Highlight::new(HlTag::Symbol(SymbolKind::Variant)),
         Definition::Const(konst) => {
-            let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Const));
+            let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Const)) | HlMod::Const;
 
             if let Some(item) = konst.as_assoc_item(db) {
                 h |= HlMod::Associated;
+                h |= HlMod::Static;
                 match item.container(db) {
                     hir::AssocItemContainer::Impl(i) => {
                         if i.trait_(db).is_some() {
@@ -445,6 +469,7 @@ pub(super) fn highlight_def(
 
             if let Some(item) = type_.as_assoc_item(db) {
                 h |= HlMod::Associated;
+                h |= HlMod::Static;
                 match item.container(db) {
                     hir::AssocItemContainer::Impl(i) => {
                         if i.trait_(db).is_some() {
@@ -474,7 +499,7 @@ pub(super) fn highlight_def(
         Definition::GenericParam(it) => match it {
             hir::GenericParam::TypeParam(_) => Highlight::new(HlTag::Symbol(SymbolKind::TypeParam)),
             hir::GenericParam::ConstParam(_) => {
-                Highlight::new(HlTag::Symbol(SymbolKind::ConstParam))
+                Highlight::new(HlTag::Symbol(SymbolKind::ConstParam)) | HlMod::Const
             }
             hir::GenericParam::LifetimeParam(_) => {
                 Highlight::new(HlTag::Symbol(SymbolKind::LifetimeParam))
@@ -550,8 +575,7 @@ fn highlight_method_call(
 ) -> Option<Highlight> {
     let func = sema.resolve_method_call(method_call)?;
 
-    let mut h = SymbolKind::Function.into();
-    h |= HlMod::Associated;
+    let mut h = SymbolKind::Method.into();
 
     if func.is_unsafe_to_call(sema.db) || sema.is_unsafe_method_call(method_call) {
         h |= HlMod::Unsafe;
@@ -647,7 +671,7 @@ fn highlight_name_ref_by_syntax(
     match parent.kind() {
         METHOD_CALL_EXPR => ast::MethodCallExpr::cast(parent)
             .and_then(|it| highlight_method_call(sema, krate, &it))
-            .unwrap_or_else(|| SymbolKind::Function.into()),
+            .unwrap_or_else(|| SymbolKind::Method.into()),
         FIELD_EXPR => {
             let h = HlTag::Symbol(SymbolKind::Field);
             let is_union = ast::FieldExpr::cast(parent)
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 a6dca0541e5..e754b702dee 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
@@ -109,6 +109,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
+.const              { font-weight: bolder; }
 
 .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
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 5163a0de417..5c7a463ccdc 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
@@ -46,7 +46,7 @@ pub enum HlTag {
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
 #[repr(u8)]
 pub enum HlMod {
-    /// Used for items in traits and impls.
+    /// Used for associated items.
     Associated = 0,
     /// Used with keywords like `async` and `await`.
     Async,
@@ -54,6 +54,8 @@ pub enum HlMod {
     Attribute,
     /// Callable item or value.
     Callable,
+    /// Constant operation.
+    Const,
     /// Value that is being consumed in a function call
     Consuming,
     /// Used with keywords like `if` and `break`.
@@ -82,7 +84,7 @@ pub enum HlMod {
     Public,
     /// Immutable reference.
     Reference,
-    /// Used for associated functions.
+    /// Used for associated items, except Methods. (Some languages call these static members)
     Static,
     /// Used for items in traits and trait impls.
     Trait,
@@ -147,6 +149,7 @@ impl HlTag {
                 SymbolKind::LifetimeParam => "lifetime",
                 SymbolKind::Local => "variable",
                 SymbolKind::Macro => "macro",
+                SymbolKind::Method => "method",
                 SymbolKind::ProcMacro => "proc_macro",
                 SymbolKind::Module => "module",
                 SymbolKind::SelfParam => "self_keyword",
@@ -211,6 +214,7 @@ impl HlMod {
         HlMod::Async,
         HlMod::Attribute,
         HlMod::Callable,
+        HlMod::Const,
         HlMod::Consuming,
         HlMod::ControlFlow,
         HlMod::CrateRoot,
@@ -237,6 +241,7 @@ impl HlMod {
             HlMod::Attribute => "attribute",
             HlMod::Callable => "callable",
             HlMod::Consuming => "consuming",
+            HlMod::Const => "const",
             HlMod::ControlFlow => "control",
             HlMod::CrateRoot => "crate_root",
             HlMod::DefaultLibrary => "default_library",
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
index 6994cb3d5c5..9c7f03fc158 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html
@@ -40,6 +40,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
+.const              { font-weight: bolder; }
 
 .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
@@ -50,15 +51,15 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 
 <span class="keyword">impl</span> <span class="struct">foo</span> <span class="brace">{</span>
     <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function associated declaration public static">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
-    <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function associated declaration public reference">is_not_static</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
+    <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="method associated declaration public reference">is_not_static</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
 <span class="brace">}</span>
 
 <span class="keyword">trait</span> <span class="trait declaration">t</span> <span class="brace">{</span>
     <span class="keyword">fn</span> <span class="function associated declaration static trait">t_is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
-    <span class="keyword">fn</span> <span class="function associated declaration reference trait">t_is_not_static</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
+    <span class="keyword">fn</span> <span class="method associated declaration reference trait">t_is_not_static</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
 <span class="brace">}</span>
 
 <span class="keyword">impl</span> <span class="trait">t</span> <span class="keyword">for</span> <span class="struct">foo</span> <span class="brace">{</span>
     <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function associated declaration public static trait">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
-    <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function associated declaration public reference trait">is_not_static</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
+    <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="method associated declaration public reference trait">is_not_static</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
 <span class="brace">}</span></code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html
index dc2d103b581..de902b5137d 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html
@@ -40,6 +40,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
+.const              { font-weight: bolder; }
 
 .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
@@ -47,7 +48,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <pre><code><span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">allow</span><span class="parenthesis attribute">(</span><span class="none attribute">dead_code</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="tool_module attribute library">rustfmt</span><span class="operator attribute">::</span><span class="tool_module attribute library">skip</span><span class="attribute_bracket attribute">]</span>
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="module attribute crate_root library">proc_macros</span><span class="operator attribute">::</span><span class="attribute attribute library">identity</span><span class="attribute_bracket attribute">]</span>
-<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="derive attribute default_library library">Copy</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
+<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="derive attribute default_library library">Default</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
 <span class="comment documentation">/// This is a doc comment</span>
 <span class="comment">// This is a normal comment</span>
 <span class="comment documentation">/// This is a doc comment</span>
@@ -57,4 +58,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="comment">// This is another normal comment</span>
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="derive attribute default_library library">Copy</span><span class="comma attribute">,</span> <span class="unresolved_reference attribute">Unresolved</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
 <span class="comment">// The reason for these being here is to test AttrIds</span>
-<span class="keyword">struct</span> <span class="struct declaration">Foo</span><span class="semicolon">;</span></code></pre>
\ No newline at end of file
+<span class="keyword">enum</span> <span class="enum declaration">Foo</span> <span class="brace">{</span>
+    <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="derive_helper attribute default_library library">default</span><span class="attribute_bracket attribute">]</span>
+    <span class="enum_variant declaration">Bar</span>
+<span class="brace">}</span></code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html
index 093cc2358a6..eed3968a906 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html
@@ -40,6 +40,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
+.const              { font-weight: bolder; }
 
 .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
@@ -58,7 +59,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
         <span class="unresolved_reference">foo</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">Bar</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
         <span class="keyword">fn</span> <span class="function declaration">func</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
             <span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="brace">{</span>
-                <span class="keyword">struct</span> <span class="struct declaration">Innerest</span><span class="angle">&lt;</span><span class="keyword">const</span> <span class="const_param declaration">C</span><span class="colon">:</span> <span class="unresolved_reference">usize</span><span class="angle">&gt;</span> <span class="brace">{</span> <span class="field declaration">field</span><span class="colon">:</span> <span class="bracket">[</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="brace">{</span><span class="const_param">C</span><span class="brace">}</span><span class="bracket">]</span> <span class="brace">}</span>
+                <span class="keyword">struct</span> <span class="struct declaration">Innerest</span><span class="angle">&lt;</span><span class="keyword">const</span> <span class="const_param const declaration">C</span><span class="colon">:</span> <span class="unresolved_reference">usize</span><span class="angle">&gt;</span> <span class="brace">{</span> <span class="field declaration">field</span><span class="colon">:</span> <span class="bracket">[</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="brace">{</span><span class="const_param const">C</span><span class="brace">}</span><span class="bracket">]</span> <span class="brace">}</span>
             <span class="brace">}</span>
         <span class="brace">}</span>
     <span class="brace">}</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html
new file mode 100644
index 00000000000..cd6ffc2c3ae
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html
@@ -0,0 +1,83 @@
+
+<style>
+body                { margin: 0; }
+pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
+
+.lifetime           { color: #DFAF8F; font-style: italic; }
+.label              { color: #DFAF8F; font-style: italic; }
+.comment            { color: #7F9F7F; }
+.documentation      { color: #629755; }
+.intra_doc_link     { font-style: italic; }
+.injected           { opacity: 0.65 ; }
+.struct, .enum      { color: #7CB8BB; }
+.enum_variant       { color: #BDE0F3; }
+.string_literal     { color: #CC9393; }
+.field              { color: #94BFF3; }
+.function           { color: #93E0E3; }
+.function.unsafe    { color: #BC8383; }
+.trait.unsafe       { color: #BC8383; }
+.operator.unsafe    { color: #BC8383; }
+.mutable.unsafe     { color: #BC8383; text-decoration: underline; }
+.keyword.unsafe     { color: #BC8383; font-weight: bold; }
+.macro.unsafe       { color: #BC8383; }
+.parameter          { color: #94BFF3; }
+.text               { color: #DCDCCC; }
+.type               { color: #7CB8BB; }
+.builtin_type       { color: #8CD0D3; }
+.type_param         { color: #DFAF8F; }
+.attribute          { color: #94BFF3; }
+.numeric_literal    { color: #BFEBBF; }
+.bool_literal       { color: #BFE6EB; }
+.macro              { color: #94BFF3; }
+.proc_macro         { color: #94BFF3; text-decoration: underline; }
+.derive             { color: #94BFF3; font-style: italic; }
+.module             { color: #AFD8AF; }
+.value_param        { color: #DCDCCC; }
+.variable           { color: #DCDCCC; }
+.format_specifier   { color: #CC696B; }
+.mutable            { text-decoration: underline; }
+.escape_sequence    { color: #94BFF3; }
+.keyword            { color: #F0DFAF; font-weight: bold; }
+.control            { font-style: italic; }
+.reference          { font-style: italic; font-weight: bold; }
+.const              { font-weight: bolder; }
+
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
+</style>
+<pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">id</span> <span class="brace">{</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span>
+        <span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span>
+    <span class="brace">}</span><span class="semicolon">;</span>
+<span class="brace">}</span>
+<span class="keyword const">const</span> <span class="constant const declaration">CONST_ITEM</span><span class="colon">:</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span> <span class="operator">&</span><span class="keyword">raw</span> <span class="keyword">const</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+<span class="keyword const">const</span> <span class="keyword">fn</span> <span class="function const declaration">const_fn</span><span class="angle">&lt;</span><span class="keyword">const</span> <span class="const_param const declaration">CONST_PARAM</span><span class="colon">:</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="keyword const">const</span> <span class="brace">{</span><span class="brace">}</span><span class="colon">:</span> <span class="keyword">const</span> <span class="keyword">fn</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="parenthesis">)</span> <span class="keyword">where</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="colon">:</span> <span class="keyword const">const</span> <span class="trait">ConstTrait</span> <span class="brace">{</span>
+    <span class="constant const">CONST_ITEM</span><span class="semicolon">;</span>
+    <span class="const_param const">CONST_PARAM</span><span class="semicolon">;</span>
+    <span class="keyword const">const</span> <span class="brace">{</span>
+        <span class="keyword">const</span> <span class="punctuation">|</span><span class="punctuation">|</span> <span class="brace">{</span><span class="brace">}</span>
+    <span class="brace">}</span>
+    <span class="macro">id</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>
+        <span class="constant const macro">CONST_ITEM</span><span class="semicolon macro">;</span>
+        <span class="const_param const macro">CONST_PARAM</span><span class="semicolon macro">;</span>
+        <span class="keyword const macro">const</span> <span class="brace macro">{</span>
+            <span class="keyword macro">const</span> <span class="punctuation macro">|</span><span class="punctuation macro">|</span> <span class="brace macro">{</span><span class="brace macro">}</span>
+        <span class="brace macro">}</span><span class="semicolon macro">;</span>
+        <span class="operator macro">&</span><span class="keyword macro">raw</span> <span class="keyword macro">const</span> <span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="semicolon macro">;</span>
+        <span class="keyword macro">const</span>
+    <span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="brace">}</span>
+<span class="keyword">trait</span> <span class="trait declaration">ConstTrait</span> <span class="brace">{</span>
+    <span class="keyword const">const</span> <span class="constant associated const declaration static trait">ASSOC_CONST</span><span class="colon">:</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="keyword const">const</span> <span class="keyword">fn</span> <span class="function associated const declaration static trait">assoc_const_fn</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
+<span class="brace">}</span>
+<span class="keyword">impl</span> <span class="keyword const">const</span> <span class="trait">ConstTrait</span> <span class="keyword">for</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
+    <span class="keyword const">const</span> <span class="constant associated const declaration static trait">ASSOC_CONST</span><span class="colon">:</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="keyword const">const</span> <span class="keyword">fn</span> <span class="function associated const declaration static trait">assoc_const_fn</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
+<span class="brace">}</span>
+
+<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">unsafe_deref</span> <span class="brace">{</span>
+    <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span>
+        <span class="punctuation">*</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="keyword">as</span> <span class="punctuation">*</span><span class="keyword">const</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="parenthesis">)</span>
+    <span class="brace">}</span><span class="semicolon">;</span>
+<span class="brace">}</span></code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html
index 154b823fffb..63e1560b921 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html
@@ -40,6 +40,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
+.const              { font-weight: bolder; }
 
 .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
@@ -47,7 +48,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root library">foo</span><span class="semicolon">;</span>
 <span class="keyword">use</span> <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">iter</span><span class="semicolon">;</span>
 
-<span class="keyword">pub</span> <span class="keyword">const</span> <span class="constant declaration public">NINETY_TWO</span><span class="colon">:</span> <span class="builtin_type">u8</span> <span class="operator">=</span> <span class="numeric_literal">92</span><span class="semicolon">;</span>
+<span class="keyword">pub</span> <span class="keyword const">const</span> <span class="constant const declaration public">NINETY_TWO</span><span class="colon">:</span> <span class="builtin_type">u8</span> <span class="operator">=</span> <span class="numeric_literal">92</span><span class="semicolon">;</span>
 
 <span class="keyword">use</span> <span class="module crate_root library">foo</span> <span class="keyword">as</span> <span class="module crate_root declaration library">foooo</span><span class="semicolon">;</span>
 
@@ -56,13 +57,13 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="brace">}</span>
 
 <span class="keyword">mod</span> <span class="module declaration">bar</span> <span class="brace">{</span>
-    <span class="keyword">pub</span><span class="parenthesis">(</span><span class="keyword control">in</span> <span class="keyword crate_root public">super</span><span class="parenthesis">)</span> <span class="keyword">const</span> <span class="constant declaration">FORTY_TWO</span><span class="colon">:</span> <span class="builtin_type">u8</span> <span class="operator">=</span> <span class="numeric_literal">42</span><span class="semicolon">;</span>
+    <span class="keyword">pub</span><span class="parenthesis">(</span><span class="keyword control">in</span> <span class="keyword crate_root public">super</span><span class="parenthesis">)</span> <span class="keyword const">const</span> <span class="constant const declaration">FORTY_TWO</span><span class="colon">:</span> <span class="builtin_type">u8</span> <span class="operator">=</span> <span class="numeric_literal">42</span><span class="semicolon">;</span>
 
     <span class="keyword">mod</span> <span class="module declaration">baz</span> <span class="brace">{</span>
-        <span class="keyword">use</span> <span class="keyword">super</span><span class="operator">::</span><span class="keyword crate_root public">super</span><span class="operator">::</span><span class="constant public">NINETY_TWO</span><span class="semicolon">;</span>
+        <span class="keyword">use</span> <span class="keyword">super</span><span class="operator">::</span><span class="keyword crate_root public">super</span><span class="operator">::</span><span class="constant const public">NINETY_TWO</span><span class="semicolon">;</span>
         <span class="keyword">use</span> <span class="keyword crate_root public">crate</span><span class="operator">::</span><span class="module crate_root library">foooo</span><span class="operator">::</span><span class="struct library">Point</span><span class="semicolon">;</span>
 
-        <span class="keyword">pub</span><span class="parenthesis">(</span><span class="keyword control">in</span> <span class="keyword">super</span><span class="operator">::</span><span class="keyword crate_root public">super</span><span class="parenthesis">)</span> <span class="keyword">const</span> <span class="constant declaration">TWENTY_NINE</span><span class="colon">:</span> <span class="builtin_type">u8</span> <span class="operator">=</span> <span class="numeric_literal">29</span><span class="semicolon">;</span>
+        <span class="keyword">pub</span><span class="parenthesis">(</span><span class="keyword control">in</span> <span class="keyword">super</span><span class="operator">::</span><span class="keyword crate_root public">super</span><span class="parenthesis">)</span> <span class="keyword const">const</span> <span class="constant const declaration">TWENTY_NINE</span><span class="colon">:</span> <span class="builtin_type">u8</span> <span class="operator">=</span> <span class="numeric_literal">29</span><span class="semicolon">;</span>
     <span class="brace">}</span>
 <span class="brace">}</span>
 </code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html
index 58613bf1510..366895ce7ec 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_default_library.html
@@ -40,6 +40,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
+.const              { font-weight: bolder; }
 
 .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
@@ -48,5 +49,5 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 
 <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
     <span class="keyword">let</span> <span class="variable declaration">foo</span> <span class="operator">=</span> <span class="enum_variant default_library library">Some</span><span class="parenthesis">(</span><span class="numeric_literal">92</span><span class="parenthesis">)</span><span class="semicolon">;</span>
-    <span class="keyword">let</span> <span class="variable declaration">nums</span> <span class="operator">=</span> <span class="module default_library library">iter</span><span class="operator">::</span><span class="function default_library library">repeat</span><span class="parenthesis">(</span><span class="variable">foo</span><span class="operator">.</span><span class="function associated consuming default_library library">unwrap</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="keyword">let</span> <span class="variable declaration">nums</span> <span class="operator">=</span> <span class="module default_library library">iter</span><span class="operator">::</span><span class="function default_library library">repeat</span><span class="parenthesis">(</span><span class="variable">foo</span><span class="operator">.</span><span class="method consuming default_library library">unwrap</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="brace">}</span></code></pre>
\ No newline at end of file
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 34274932afc..b2ca6e1ca4b 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
@@ -40,6 +40,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
+.const              { font-weight: bolder; }
 
 .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
@@ -71,7 +72,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="comment">//    KILLER WHALE</span>
     <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="string_literal injected">    Ishmael."</span><span class="semicolon injected">;</span>
     <span class="comment documentation">/// ```</span>
-    <span class="keyword">pub</span> <span class="keyword">const</span> <span class="constant associated declaration public">bar</span><span class="colon">:</span> <span class="builtin_type">bool</span> <span class="operator">=</span> <span class="bool_literal">true</span><span class="semicolon">;</span>
+    <span class="keyword">pub</span> <span class="keyword const">const</span> <span class="constant associated const declaration public static">bar</span><span class="colon">:</span> <span class="builtin_type">bool</span> <span class="operator">=</span> <span class="bool_literal">true</span><span class="semicolon">;</span>
 
     <span class="comment documentation">/// Constructs a new `Foo`.</span>
     <span class="comment documentation">///</span>
@@ -81,7 +82,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="comment documentation">///</span><span class="comment documentation"> #</span><span class="none injected"> </span><span class="attribute_bracket attribute injected">#</span><span class="attribute_bracket attribute injected">!</span><span class="attribute_bracket attribute injected">[</span><span class="builtin_attr attribute injected library">allow</span><span class="parenthesis attribute injected">(</span><span class="none attribute injected">unused_mut</span><span class="parenthesis attribute injected">)</span><span class="attribute_bracket attribute injected">]</span>
     <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="keyword injected">mut</span><span class="none injected"> </span><span class="variable declaration injected mutable">foo</span><span class="colon injected">:</span><span class="none injected"> </span><span class="struct injected">Foo</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span>
     <span class="comment documentation">/// ```</span>
-    <span class="keyword">pub</span> <span class="keyword">const</span> <span class="keyword">fn</span> <span class="function associated declaration public static">new</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="struct">Foo</span> <span class="brace">{</span>
+    <span class="keyword">pub</span> <span class="keyword const">const</span> <span class="keyword">fn</span> <span class="function associated const declaration public static">new</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="struct">Foo</span> <span class="brace">{</span>
         <span class="struct">Foo</span> <span class="brace">{</span> <span class="field">bar</span><span class="colon">:</span> <span class="bool_literal">true</span> <span class="brace">}</span>
     <span class="brace">}</span>
 
@@ -109,25 +110,25 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="comment documentation">/// ```</span>
     <span class="comment documentation">///</span>
     <span class="comment documentation">/// ```rust,no_run</span>
-    <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="variable declaration injected">foobar</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="operator injected">.</span><span class="function injected">bar</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span>
+    <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="variable declaration injected">foobar</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="operator injected">.</span><span class="method injected">bar</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span>
     <span class="comment documentation">/// ```</span>
     <span class="comment documentation">///</span>
     <span class="comment documentation">/// ~~~rust,no_run</span>
     <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="comment injected">// code block with tilde.</span>
-    <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="variable declaration injected">foobar</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="operator injected">.</span><span class="function injected">bar</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span>
+    <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="variable declaration injected">foobar</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="operator injected">.</span><span class="method injected">bar</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span>
     <span class="comment documentation">/// ~~~</span>
     <span class="comment documentation">///</span>
     <span class="comment documentation">/// ```</span>
     <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="comment injected">// functions</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="angle injected">&lt;</span><span class="type_param declaration injected">T</span><span class="comma injected">,</span><span class="none injected"> </span><span class="keyword injected">const</span><span class="none injected"> </span><span class="const_param declaration injected">X</span><span class="colon injected">:</span><span class="none injected"> </span><span class="builtin_type injected">usize</span><span class="angle injected">&gt;</span><span class="parenthesis injected">(</span><span class="value_param declaration injected">arg</span><span class="colon injected">:</span><span class="none injected"> </span><span class="builtin_type injected">i32</span><span class="parenthesis injected">)</span><span class="none injected"> </span><span class="brace injected">{</span>
-    <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="none injected">    </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="variable declaration injected">x</span><span class="colon injected">:</span><span class="none injected"> </span><span class="type_param injected">T</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="const_param injected">X</span><span class="semicolon injected">;</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="angle injected">&lt;</span><span class="type_param declaration injected">T</span><span class="comma injected">,</span><span class="none injected"> </span><span class="keyword injected">const</span><span class="none injected"> </span><span class="const_param const declaration injected">X</span><span class="colon injected">:</span><span class="none injected"> </span><span class="builtin_type injected">usize</span><span class="angle injected">&gt;</span><span class="parenthesis injected">(</span><span class="value_param declaration injected">arg</span><span class="colon injected">:</span><span class="none injected"> </span><span class="builtin_type injected">i32</span><span class="parenthesis injected">)</span><span class="none injected"> </span><span class="brace injected">{</span>
+    <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="none injected">    </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="variable declaration injected">x</span><span class="colon injected">:</span><span class="none injected"> </span><span class="type_param injected">T</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="const_param const injected">X</span><span class="semicolon injected">;</span>
     <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="brace injected">}</span>
     <span class="comment documentation">/// ```</span>
     <span class="comment documentation">///</span>
     <span class="comment documentation">/// ```sh</span>
     <span class="comment documentation">/// echo 1</span>
     <span class="comment documentation">/// ```</span>
-    <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function associated declaration public reference">foo</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">bool</span> <span class="brace">{</span>
+    <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="method associated declaration public reference">foo</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">bool</span> <span class="brace">{</span>
         <span class="bool_literal">true</span>
     <span class="brace">}</span>
 <span class="brace">}</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html
index 729e4791f55..129b287e52f 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_extern_crate.html
@@ -40,6 +40,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
+.const              { font-weight: bolder; }
 
 .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
index 066fcfb1dfe..7ba1194d675 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
@@ -40,6 +40,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
+.const              { font-weight: bolder; }
 
 .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
@@ -63,25 +64,25 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="brace">}</span>
 
 <span class="keyword">trait</span> <span class="trait declaration">Bar</span> <span class="brace">{</span>
-    <span class="keyword">fn</span> <span class="function associated declaration reference trait">bar</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span><span class="semicolon">;</span>
+    <span class="keyword">fn</span> <span class="method associated declaration reference trait">bar</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 
 <span class="keyword">impl</span> <span class="trait">Bar</span> <span class="keyword">for</span> <span class="struct">Foo</span> <span class="brace">{</span>
-    <span class="keyword">fn</span> <span class="function associated declaration reference trait">bar</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span>
+    <span class="keyword">fn</span> <span class="method associated declaration reference trait">bar</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span>
         <span class="self_keyword reference">self</span><span class="operator">.</span><span class="field">x</span>
     <span class="brace">}</span>
 <span class="brace">}</span>
 
 <span class="keyword">impl</span> <span class="struct">Foo</span> <span class="brace">{</span>
-    <span class="keyword">fn</span> <span class="function associated consuming declaration">baz</span><span class="parenthesis">(</span><span class="keyword">mut</span> <span class="self_keyword declaration mutable">self</span><span class="comma">,</span> <span class="value_param declaration">f</span><span class="colon">:</span> <span class="struct">Foo</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span>
-        <span class="value_param">f</span><span class="operator">.</span><span class="function associated consuming">baz</span><span class="parenthesis">(</span><span class="self_keyword consuming mutable">self</span><span class="parenthesis">)</span>
+    <span class="keyword">fn</span> <span class="method associated consuming declaration">baz</span><span class="parenthesis">(</span><span class="keyword">mut</span> <span class="self_keyword declaration mutable">self</span><span class="comma">,</span> <span class="value_param declaration">f</span><span class="colon">:</span> <span class="struct">Foo</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span>
+        <span class="value_param">f</span><span class="operator">.</span><span class="method consuming">baz</span><span class="parenthesis">(</span><span class="self_keyword consuming mutable">self</span><span class="parenthesis">)</span>
     <span class="brace">}</span>
 
-    <span class="keyword">fn</span> <span class="function associated declaration mutable reference">qux</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="keyword">mut</span> <span class="self_keyword declaration mutable reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span>
+    <span class="keyword">fn</span> <span class="method associated declaration mutable reference">qux</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="keyword">mut</span> <span class="self_keyword declaration mutable reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span>
         <span class="self_keyword mutable reference">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span>
     <span class="brace">}</span>
 
-    <span class="keyword">fn</span> <span class="function associated declaration reference">quop</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span>
+    <span class="keyword">fn</span> <span class="method associated declaration reference">quop</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">i32</span> <span class="brace">{</span>
         <span class="self_keyword reference">self</span><span class="operator">.</span><span class="field">x</span>
     <span class="brace">}</span>
 <span class="brace">}</span>
@@ -94,15 +95,15 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="brace">}</span>
 
 <span class="keyword">impl</span> <span class="struct">FooCopy</span> <span class="brace">{</span>
-    <span class="keyword">fn</span> <span class="function associated consuming declaration">baz</span><span class="parenthesis">(</span><span class="self_keyword declaration">self</span><span class="comma">,</span> <span class="value_param declaration">f</span><span class="colon">:</span> <span class="struct">FooCopy</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="brace">{</span>
-        <span class="value_param">f</span><span class="operator">.</span><span class="function associated">baz</span><span class="parenthesis">(</span><span class="self_keyword">self</span><span class="parenthesis">)</span>
+    <span class="keyword">fn</span> <span class="method associated consuming declaration">baz</span><span class="parenthesis">(</span><span class="self_keyword declaration">self</span><span class="comma">,</span> <span class="value_param declaration">f</span><span class="colon">:</span> <span class="struct">FooCopy</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="brace">{</span>
+        <span class="value_param">f</span><span class="operator">.</span><span class="method">baz</span><span class="parenthesis">(</span><span class="self_keyword">self</span><span class="parenthesis">)</span>
     <span class="brace">}</span>
 
-    <span class="keyword">fn</span> <span class="function associated declaration mutable reference">qux</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="keyword">mut</span> <span class="self_keyword declaration mutable reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span>
+    <span class="keyword">fn</span> <span class="method associated declaration mutable reference">qux</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="keyword">mut</span> <span class="self_keyword declaration mutable reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span>
         <span class="self_keyword mutable reference">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span>
     <span class="brace">}</span>
 
-    <span class="keyword">fn</span> <span class="function associated declaration reference">quop</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="brace">{</span>
+    <span class="keyword">fn</span> <span class="method associated declaration reference">quop</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">u32</span> <span class="brace">{</span>
         <span class="self_keyword reference">self</span><span class="operator">.</span><span class="field">x</span>
     <span class="brace">}</span>
 <span class="brace">}</span>
@@ -119,9 +120,9 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="keyword control">loop</span> <span class="brace">{</span><span class="brace">}</span>
 <span class="brace">}</span>
 
-<span class="keyword">fn</span> <span class="function declaration">const_param</span><span class="angle">&lt;</span><span class="keyword">const</span> <span class="const_param declaration">FOO</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">usize</span> <span class="brace">{</span>
-    <span class="function">const_param</span><span class="operator">::</span><span class="angle">&lt;</span><span class="brace">{</span> <span class="const_param">FOO</span> <span class="brace">}</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
-    <span class="const_param">FOO</span>
+<span class="keyword">fn</span> <span class="function declaration">const_param</span><span class="angle">&lt;</span><span class="keyword">const</span> <span class="const_param const declaration">FOO</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">usize</span> <span class="brace">{</span>
+    <span class="function">const_param</span><span class="operator">::</span><span class="angle">&lt;</span><span class="brace">{</span> <span class="const_param const">FOO</span> <span class="brace">}</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="const_param const">FOO</span>
 <span class="brace">}</span>
 
 <span class="keyword">use</span> <span class="module public">ops</span><span class="operator">::</span><span class="trait public">Fn</span><span class="semicolon">;</span>
@@ -148,17 +149,17 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 
     <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">foo</span> <span class="operator">=</span> <span class="struct">Foo</span> <span class="brace">{</span> <span class="field">x</span><span class="comma">,</span> <span class="unresolved_reference">y</span><span class="colon">:</span> <span class="variable mutable">x</span> <span class="brace">}</span><span class="semicolon">;</span>
     <span class="keyword">let</span> <span class="variable declaration">foo2</span> <span class="operator">=</span> <span class="struct">Foo</span> <span class="brace">{</span> <span class="field">x</span><span class="comma">,</span> <span class="unresolved_reference">y</span><span class="colon">:</span> <span class="variable mutable">x</span> <span class="brace">}</span><span class="semicolon">;</span>
-    <span class="variable mutable">foo</span><span class="operator">.</span><span class="function associated reference">quop</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
-    <span class="variable mutable">foo</span><span class="operator">.</span><span class="function associated mutable reference">qux</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
-    <span class="variable mutable">foo</span><span class="operator">.</span><span class="function associated consuming">baz</span><span class="parenthesis">(</span><span class="variable consuming">foo2</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="variable mutable">foo</span><span class="operator">.</span><span class="method reference">quop</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="variable mutable">foo</span><span class="operator">.</span><span class="method mutable reference">qux</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="variable mutable">foo</span><span class="operator">.</span><span class="method consuming">baz</span><span class="parenthesis">(</span><span class="variable consuming">foo2</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
     <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">copy</span> <span class="operator">=</span> <span class="struct">FooCopy</span> <span class="brace">{</span> <span class="field">x</span> <span class="brace">}</span><span class="semicolon">;</span>
-    <span class="variable mutable">copy</span><span class="operator">.</span><span class="function associated reference">quop</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
-    <span class="variable mutable">copy</span><span class="operator">.</span><span class="function associated mutable reference">qux</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
-    <span class="variable mutable">copy</span><span class="operator">.</span><span class="function associated">baz</span><span class="parenthesis">(</span><span class="variable mutable">copy</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="variable mutable">copy</span><span class="operator">.</span><span class="method reference">quop</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="variable mutable">copy</span><span class="operator">.</span><span class="method mutable reference">qux</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="variable mutable">copy</span><span class="operator">.</span><span class="method">baz</span><span class="parenthesis">(</span><span class="variable mutable">copy</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
     <span class="keyword">let</span> <span class="variable callable declaration">a</span> <span class="operator">=</span> <span class="punctuation">|</span><span class="value_param declaration">x</span><span class="punctuation">|</span> <span class="value_param">x</span><span class="semicolon">;</span>
-    <span class="keyword">let</span> <span class="variable callable declaration">bar</span> <span class="operator">=</span> <span class="struct">Foo</span><span class="operator">::</span><span class="function associated consuming">baz</span><span class="semicolon">;</span>
+    <span class="keyword">let</span> <span class="variable callable declaration">bar</span> <span class="operator">=</span> <span class="struct">Foo</span><span class="operator">::</span><span class="method associated consuming">baz</span><span class="semicolon">;</span>
 
     <span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="numeric_literal">-</span><span class="numeric_literal">42</span><span class="comma">,</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="operator">-</span><span class="variable">baz</span><span class="operator">.</span><span class="field">0</span><span class="semicolon">;</span>
@@ -178,7 +179,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="keyword">use</span> <span class="enum">Option</span><span class="operator">::</span><span class="punctuation">*</span><span class="semicolon">;</span>
 
 <span class="keyword">impl</span><span class="angle">&lt;</span><span class="type_param declaration">T</span><span class="angle">&gt;</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="type_param">T</span><span class="angle">&gt;</span> <span class="brace">{</span>
-    <span class="keyword">fn</span> <span class="function associated consuming declaration">and</span><span class="angle">&lt;</span><span class="type_param declaration">U</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="self_keyword declaration">self</span><span class="comma">,</span> <span class="value_param declaration">other</span><span class="colon">:</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="type_param">U</span><span class="angle">&gt;</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="parenthesis">(</span><span class="type_param">T</span><span class="comma">,</span> <span class="type_param">U</span><span class="parenthesis">)</span><span class="angle">&gt;</span> <span class="brace">{</span>
+    <span class="keyword">fn</span> <span class="method associated consuming declaration">and</span><span class="angle">&lt;</span><span class="type_param declaration">U</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="self_keyword declaration">self</span><span class="comma">,</span> <span class="value_param declaration">other</span><span class="colon">:</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="type_param">U</span><span class="angle">&gt;</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="parenthesis">(</span><span class="type_param">T</span><span class="comma">,</span> <span class="type_param">U</span><span class="parenthesis">)</span><span class="angle">&gt;</span> <span class="brace">{</span>
         <span class="keyword control">match</span> <span class="value_param">other</span> <span class="brace">{</span>
             <span class="enum_variant">None</span> <span class="operator">=&gt;</span> <span class="unresolved_reference">unimplemented</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="comma">,</span>
             <span class="variable declaration">Nope</span> <span class="operator">=&gt;</span> <span class="variable">Nope</span><span class="comma">,</span>
@@ -200,12 +201,12 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="keyword">fn</span> <span class="function declaration">use_foo_items</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
     <span class="keyword">let</span> <span class="variable declaration">bob</span> <span class="operator">=</span> <span class="module crate_root library">foo</span><span class="operator">::</span><span class="struct library">Person</span> <span class="brace">{</span>
         <span class="field library">name</span><span class="colon">:</span> <span class="string_literal">"Bob"</span><span class="comma">,</span>
-        <span class="field library">age</span><span class="colon">:</span> <span class="module crate_root library">foo</span><span class="operator">::</span><span class="module library">consts</span><span class="operator">::</span><span class="constant library">NUMBER</span><span class="comma">,</span>
+        <span class="field library">age</span><span class="colon">:</span> <span class="module crate_root library">foo</span><span class="operator">::</span><span class="module library">consts</span><span class="operator">::</span><span class="constant const library">NUMBER</span><span class="comma">,</span>
     <span class="brace">}</span><span class="semicolon">;</span>
 
     <span class="keyword">let</span> <span class="variable declaration">control_flow</span> <span class="operator">=</span> <span class="module crate_root library">foo</span><span class="operator">::</span><span class="function library">identity</span><span class="parenthesis">(</span><span class="module crate_root library">foo</span><span class="operator">::</span><span class="enum library">ControlFlow</span><span class="operator">::</span><span class="enum_variant library">Continue</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
-    <span class="keyword control">if</span> <span class="variable">control_flow</span><span class="operator">.</span><span class="function associated consuming library">should_die</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
+    <span class="keyword control">if</span> <span class="variable">control_flow</span><span class="operator">.</span><span class="method consuming library">should_die</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
         <span class="module crate_root library">foo</span><span class="operator">::</span><span class="unresolved_reference">die</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
     <span class="brace">}</span>
 <span class="brace">}</span>
@@ -213,23 +214,23 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="keyword">pub</span> <span class="keyword">enum</span> <span class="enum declaration public">Bool</span> <span class="brace">{</span> <span class="enum_variant declaration public">True</span><span class="comma">,</span> <span class="enum_variant declaration public">False</span> <span class="brace">}</span>
 
 <span class="keyword">impl</span> <span class="enum public">Bool</span> <span class="brace">{</span>
-    <span class="keyword">pub</span> <span class="keyword">const</span> <span class="keyword">fn</span> <span class="function associated consuming declaration public">to_primitive</span><span class="parenthesis">(</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">bool</span> <span class="brace">{</span>
+    <span class="keyword">pub</span> <span class="keyword const">const</span> <span class="keyword">fn</span> <span class="method associated const consuming declaration public">to_primitive</span><span class="parenthesis">(</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="builtin_type">bool</span> <span class="brace">{</span>
         <span class="bool_literal">true</span>
     <span class="brace">}</span>
 <span class="brace">}</span>
-<span class="keyword">const</span> <span class="constant declaration">USAGE_OF_BOOL</span><span class="colon">:</span><span class="builtin_type">bool</span> <span class="operator">=</span> <span class="enum public">Bool</span><span class="operator">::</span><span class="enum_variant public">True</span><span class="operator">.</span><span class="function associated consuming public">to_primitive</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+<span class="keyword const">const</span> <span class="constant const declaration">USAGE_OF_BOOL</span><span class="colon">:</span><span class="builtin_type">bool</span> <span class="operator">=</span> <span class="enum public">Bool</span><span class="operator">::</span><span class="enum_variant public">True</span><span class="operator">.</span><span class="method consuming public">to_primitive</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
 <span class="keyword">trait</span> <span class="trait declaration">Baz</span> <span class="brace">{</span>
-    <span class="keyword">type</span> <span class="type_alias associated declaration trait">Qux</span><span class="semicolon">;</span>
+    <span class="keyword">type</span> <span class="type_alias associated declaration static trait">Qux</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 
 <span class="keyword">fn</span> <span class="function declaration">baz</span><span class="angle">&lt;</span><span class="type_param declaration">T</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="value_param declaration">t</span><span class="colon">:</span> <span class="type_param">T</span><span class="parenthesis">)</span>
 <span class="keyword">where</span>
     <span class="type_param">T</span><span class="colon">:</span> <span class="trait">Baz</span><span class="comma">,</span>
-    <span class="angle">&lt;</span><span class="type_param">T</span> <span class="keyword">as</span> <span class="trait">Baz</span><span class="angle">&gt;</span><span class="operator">::</span><span class="type_alias associated trait">Qux</span><span class="colon">:</span> <span class="trait">Bar</span> <span class="brace">{</span><span class="brace">}</span>
+    <span class="angle">&lt;</span><span class="type_param">T</span> <span class="keyword">as</span> <span class="trait">Baz</span><span class="angle">&gt;</span><span class="operator">::</span><span class="type_alias associated static trait">Qux</span><span class="colon">:</span> <span class="trait">Bar</span> <span class="brace">{</span><span class="brace">}</span>
 
 <span class="keyword">fn</span> <span class="function declaration">gp_shadows_trait</span><span class="angle">&lt;</span><span class="type_param declaration">Baz</span><span class="colon">:</span> <span class="trait">Bar</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
-    <span class="type_param">Baz</span><span class="operator">::</span><span class="function associated reference trait">bar</span><span class="semicolon">;</span>
+    <span class="type_param">Baz</span><span class="operator">::</span><span class="method associated reference trait">bar</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 
 </code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
index 58a147dd80a..6c3fbcfcf41 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
@@ -40,6 +40,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
+.const              { font-weight: bolder; }
 
 .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html
index 22ae5c82a4b..7064a877070 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html
@@ -40,6 +40,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
+.const              { font-weight: bolder; }
 
 .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html
index af779996593..8428b815800 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_lifetimes.html
@@ -40,6 +40,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
+.const              { font-weight: bolder; }
 
 .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
index 32ac6a94d86..573b3d4bd52 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
@@ -40,6 +40,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
+.const              { font-weight: bolder; }
 
 .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html
index ef8a48ca1c1..947d1bf1e35 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html
@@ -40,6 +40,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
+.const              { font-weight: bolder; }
 
 .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_outline.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_outline.html
index a2ded15fd1b..0fe2b6f274d 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_outline.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_outline.html
@@ -40,6 +40,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
+.const              { font-weight: bolder; }
 
 .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_operators.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_operators.html
index d123ee04976..c60b6ab27bb 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_operators.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_operators.html
@@ -40,6 +40,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
+.const              { font-weight: bolder; }
 
 .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html
index 4429e5d933a..5d51b149789 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_rainbow.html
@@ -40,6 +40,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
+.const              { font-weight: bolder; }
 
 .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
index b6458fa7ca0..7a07d17b271 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
@@ -40,6 +40,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
+.const              { font-weight: bolder; }
 
 .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
@@ -171,9 +172,9 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
         <span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="none macro">reg</span><span class="parenthesis macro">)</span> <span class="none macro">i</span><span class="comma macro">,</span>
     <span class="parenthesis macro">)</span><span class="semicolon">;</span>
 
-    <span class="keyword">const</span> <span class="constant declaration">CONSTANT</span><span class="colon">:</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="colon">:</span>
+    <span class="keyword const">const</span> <span class="constant const declaration">CONSTANT</span><span class="colon">:</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="colon">:</span>
     <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">m</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="macro default_library library macro">concat</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"{}"</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="string_literal macro">"{}"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable reference">backslash</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="constant">CONSTANT</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable mutable">m</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="comma macro">,</span> <span class="macro default_library library macro">format_args</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="unresolved_reference macro">foo</span><span class="comma macro">,</span> <span class="string_literal macro">"bar"</span><span class="comma macro">,</span> <span class="macro macro">toho</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable reference">backslash</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="constant const">CONSTANT</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable mutable">m</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="comma macro">,</span> <span class="macro default_library library macro">format_args</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="unresolved_reference macro">foo</span><span class="comma macro">,</span> <span class="string_literal macro">"bar"</span><span class="comma macro">,</span> <span class="macro macro">toho</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
     <span class="macro">reuse_twice</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable reference">backslash</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
 <span class="brace">}</span></code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
index 49b588baa58..15d6be6334c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
@@ -40,6 +40,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .keyword            { color: #F0DFAF; font-weight: bold; }
 .control            { font-style: italic; }
 .reference          { font-style: italic; font-weight: bold; }
+.const              { font-weight: bolder; }
 
 .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
@@ -65,7 +66,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 
 <span class="keyword">struct</span> <span class="struct declaration">Struct</span> <span class="brace">{</span> <span class="field declaration">field</span><span class="colon">:</span> <span class="builtin_type">i32</span> <span class="brace">}</span>
 <span class="keyword">impl</span> <span class="struct">Struct</span> <span class="brace">{</span>
-    <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function associated declaration reference unsafe">unsafe_method</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
+    <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="method associated declaration reference unsafe">unsafe_method</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
 <span class="brace">}</span>
 
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">repr</span><span class="parenthesis attribute">(</span><span class="none attribute">packed</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
@@ -80,11 +81,11 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="keyword">fn</span> <span class="function declaration">unsafe_trait_bound</span><span class="angle">&lt;</span><span class="type_param declaration">T</span><span class="colon">:</span> <span class="trait">UnsafeTrait</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="punctuation">_</span><span class="colon">:</span> <span class="type_param">T</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
 
 <span class="keyword">trait</span> <span class="trait declaration">DoTheAutoref</span> <span class="brace">{</span>
-    <span class="keyword">fn</span> <span class="function associated declaration reference trait">calls_autoref</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="keyword">fn</span> <span class="method associated declaration reference trait">calls_autoref</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 
 <span class="keyword">impl</span> <span class="trait">DoTheAutoref</span> <span class="keyword">for</span> <span class="builtin_type">u16</span> <span class="brace">{</span>
-    <span class="keyword">fn</span> <span class="function associated declaration reference trait">calls_autoref</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
+    <span class="keyword">fn</span> <span class="method associated declaration reference trait">calls_autoref</span><span class="parenthesis">(</span><span class="punctuation">&</span><span class="self_keyword declaration reference">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
 <span class="brace">}</span>
 
 <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
@@ -106,7 +107,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
             <span class="union">Union</span> <span class="brace">{</span> <span class="field unsafe">b</span><span class="colon">:</span> <span class="numeric_literal">0</span> <span class="brace">}</span> <span class="operator">=&gt;</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="comma">,</span>
             <span class="union">Union</span> <span class="brace">{</span> <span class="field unsafe">a</span> <span class="brace">}</span> <span class="operator">=&gt;</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="comma">,</span>
         <span class="brace">}</span>
-        <span class="struct">Struct</span> <span class="brace">{</span> <span class="field">field</span><span class="colon">:</span> <span class="numeric_literal">0</span> <span class="brace">}</span><span class="operator">.</span><span class="function associated reference unsafe">unsafe_method</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+        <span class="struct">Struct</span> <span class="brace">{</span> <span class="field">field</span><span class="colon">:</span> <span class="numeric_literal">0</span> <span class="brace">}</span><span class="operator">.</span><span class="method reference unsafe">unsafe_method</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
         <span class="comment">// unsafe deref</span>
         <span class="operator unsafe">*</span><span class="variable">x</span><span class="semicolon">;</span>
@@ -123,6 +124,6 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
         <span class="keyword">let</span> <span class="struct">Packed</span> <span class="brace">{</span> <span class="field">a</span><span class="colon">:</span> <span class="keyword unsafe">ref</span> <span class="variable declaration reference">_a</span> <span class="brace">}</span> <span class="operator">=</span> <span class="variable">packed</span><span class="semicolon">;</span>
 
         <span class="comment">// unsafe auto ref of packed field</span>
-        <span class="variable">packed</span><span class="operator">.</span><span class="field">a</span><span class="operator">.</span><span class="function associated reference trait unsafe">calls_autoref</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+        <span class="variable">packed</span><span class="operator">.</span><span class="field">a</span><span class="operator">.</span><span class="method reference trait unsafe">calls_autoref</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="brace">}</span>
 <span class="brace">}</span></code></pre>
\ No newline at end of file
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 6fed7d783e8..c2990fd76ea 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
@@ -22,11 +22,11 @@ fn attributes() {
     check_highlighting(
         r#"
 //- proc_macros: identity
-//- minicore: derive, copy
+//- minicore: derive, copy, default
 #[allow(dead_code)]
 #[rustfmt::skip]
 #[proc_macros::identity]
-#[derive(Copy)]
+#[derive(Default)]
 /// This is a doc comment
 // This is a normal comment
 /// This is a doc comment
@@ -36,7 +36,10 @@ fn attributes() {
 // This is another normal comment
 #[derive(Copy, Unresolved)]
 // The reason for these being here is to test AttrIds
-struct Foo;
+enum Foo {
+    #[default]
+    Bar
+}
 "#,
         expect_file!["./test_data/highlight_attributes.html"],
         false,
@@ -630,6 +633,52 @@ fn main() {
 }
 
 #[test]
+fn test_const_highlighting() {
+    check_highlighting(
+        r#"
+macro_rules! id {
+    ($($tt:tt)*) => {
+        $($tt)*
+    };
+}
+const CONST_ITEM: *const () = &raw const ();
+const fn const_fn<const CONST_PARAM: ()>(const {}: const fn()) where (): const ConstTrait {
+    CONST_ITEM;
+    CONST_PARAM;
+    const {
+        const || {}
+    }
+    id!(
+        CONST_ITEM;
+        CONST_PARAM;
+        const {
+            const || {}
+        };
+        &raw const ();
+        const
+    );
+}
+trait ConstTrait {
+    const ASSOC_CONST: () = ();
+    const fn assoc_const_fn() {}
+}
+impl const ConstTrait for () {
+    const ASSOC_CONST: () = ();
+    const fn assoc_const_fn() {}
+}
+
+macro_rules! unsafe_deref {
+    () => {
+        *(&() as *const ())
+    };
+}
+"#,
+        expect_file!["./test_data/highlight_const.html"],
+        false,
+    );
+}
+
+#[test]
 fn test_highlight_doc_comment() {
     check_highlighting(
         r#"
@@ -1173,8 +1222,27 @@ fn benchmark_syntax_highlighting_parser() {
             .highlight(HL_CONFIG, file_id)
             .unwrap()
             .iter()
-            .filter(|it| it.highlight.tag == HlTag::Symbol(SymbolKind::Function))
+            .filter(|it| {
+                matches!(it.highlight.tag, HlTag::Symbol(SymbolKind::Function | SymbolKind::Method))
+            })
             .count()
     };
     assert_eq!(hash, 1169);
 }
+
+#[test]
+fn highlight_trait_with_lifetimes_regression_16958() {
+    let (analysis, file_id) = fixture::file(
+        r#"
+pub trait Deserialize<'de> {
+    fn deserialize();
+}
+
+fn f<'de, T: Deserialize<'de>>() {
+    T::deserialize();
+}
+"#
+        .trim(),
+    );
+    let _ = analysis.highlight(HL_CONFIG, file_id).unwrap();
+}
diff --git a/src/tools/rust-analyzer/crates/ide/src/test_explorer.rs b/src/tools/rust-analyzer/crates/ide/src/test_explorer.rs
index ca471399703..99e24308607 100644
--- a/src/tools/rust-analyzer/crates/ide/src/test_explorer.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/test_explorer.rs
@@ -7,7 +7,7 @@ use ide_db::{
 };
 use syntax::TextRange;
 
-use crate::{navigation_target::ToNav, runnables::runnable_fn, Runnable, TryToNav};
+use crate::{runnables::runnable_fn, NavigationTarget, Runnable, TryToNav};
 
 #[derive(Debug)]
 pub enum TestItemKind {
@@ -56,7 +56,12 @@ fn find_crate_by_id(crate_graph: &CrateGraph, crate_id: &str) -> Option<CrateId>
     })
 }
 
-fn discover_tests_in_module(db: &RootDatabase, module: Module, prefix_id: String) -> Vec<TestItem> {
+fn discover_tests_in_module(
+    db: &RootDatabase,
+    module: Module,
+    prefix_id: String,
+    only_in_this_file: bool,
+) -> Vec<TestItem> {
     let sema = Semantics::new(db);
 
     let mut r = vec![];
@@ -64,9 +69,9 @@ fn discover_tests_in_module(db: &RootDatabase, module: Module, prefix_id: String
         let module_name =
             c.name(db).as_ref().and_then(|n| n.as_str()).unwrap_or("[mod without name]").to_owned();
         let module_id = format!("{prefix_id}::{module_name}");
-        let module_children = discover_tests_in_module(db, c, module_id.clone());
+        let module_children = discover_tests_in_module(db, c, module_id.clone(), only_in_this_file);
         if !module_children.is_empty() {
-            let nav = c.to_nav(db).call_site;
+            let nav = NavigationTarget::from_module_to_decl(sema.db, c).call_site;
             r.push(TestItem {
                 id: module_id,
                 kind: TestItemKind::Module,
@@ -76,7 +81,9 @@ fn discover_tests_in_module(db: &RootDatabase, module: Module, prefix_id: String
                 text_range: Some(nav.focus_or_full_range()),
                 runnable: None,
             });
-            r.extend(module_children);
+            if !only_in_this_file || c.is_inline(db) {
+                r.extend(module_children);
+            }
         }
     }
     for def in module.declarations(db) {
@@ -112,6 +119,55 @@ pub(crate) fn discover_tests_in_crate_by_test_id(
     discover_tests_in_crate(db, crate_id)
 }
 
+pub(crate) fn discover_tests_in_file(db: &RootDatabase, file_id: FileId) -> Vec<TestItem> {
+    let sema = Semantics::new(db);
+
+    let Some(module) = sema.file_to_module_def(file_id) else { return vec![] };
+    let Some((mut tests, id)) = find_module_id_and_test_parents(&sema, module) else {
+        return vec![];
+    };
+    tests.extend(discover_tests_in_module(db, module, id, true));
+    tests
+}
+
+fn find_module_id_and_test_parents(
+    sema: &Semantics<'_, RootDatabase>,
+    module: Module,
+) -> Option<(Vec<TestItem>, String)> {
+    let Some(parent) = module.parent(sema.db) else {
+        let name = module.krate().display_name(sema.db)?.to_string();
+        return Some((
+            vec![TestItem {
+                id: name.clone(),
+                kind: TestItemKind::Crate(module.krate().into()),
+                label: name.clone(),
+                parent: None,
+                file: None,
+                text_range: None,
+                runnable: None,
+            }],
+            name,
+        ));
+    };
+    let (mut r, mut id) = find_module_id_and_test_parents(sema, parent)?;
+    let parent = Some(id.clone());
+    id += "::";
+    let module_name = &module.name(sema.db);
+    let module_name = module_name.as_ref().and_then(|n| n.as_str()).unwrap_or("[mod without name]");
+    id += module_name;
+    let nav = NavigationTarget::from_module_to_decl(sema.db, module).call_site;
+    r.push(TestItem {
+        id: id.clone(),
+        kind: TestItemKind::Module,
+        label: module_name.to_owned(),
+        parent,
+        file: Some(nav.file_id),
+        text_range: Some(nav.focus_or_full_range()),
+        runnable: None,
+    });
+    Some((r, id))
+}
+
 pub(crate) fn discover_tests_in_crate(db: &RootDatabase, crate_id: CrateId) -> Vec<TestItem> {
     let crate_graph = db.crate_graph();
     if !crate_graph[crate_id].origin.is_local() {
@@ -133,6 +189,6 @@ pub(crate) fn discover_tests_in_crate(db: &RootDatabase, crate_id: CrateId) -> V
         text_range: None,
         runnable: None,
     }];
-    r.extend(discover_tests_in_module(db, module, crate_test_id));
+    r.extend(discover_tests_in_module(db, module, crate_test_id, false));
     r
 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/typing.rs b/src/tools/rust-analyzer/crates/ide/src/typing.rs
index e87fc89fea2..d3eee0e02e4 100644
--- a/src/tools/rust-analyzer/crates/ide/src/typing.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/typing.rs
@@ -175,9 +175,21 @@ fn on_opening_bracket_typed(
             }
         }
 
-        // If it's a statement in a block, we don't know how many statements should be included
-        if ast::ExprStmt::can_cast(expr.syntax().parent()?.kind()) {
-            return None;
+        if let Some(parent) = expr.syntax().parent().and_then(ast::Expr::cast) {
+            let mut node = expr.syntax().clone();
+            let all_prev_sib_attr = loop {
+                match node.prev_sibling() {
+                    Some(sib) if sib.kind().is_trivia() || sib.kind() == SyntaxKind::ATTR => {
+                        node = sib
+                    }
+                    Some(_) => break false,
+                    None => break true,
+                };
+            };
+
+            if all_prev_sib_attr {
+                expr = parent;
+            }
         }
 
         // Insert the closing bracket right after the expression.
@@ -827,6 +839,21 @@ fn f() {
 }
             "#,
         );
+        type_char(
+            '{',
+            r#"
+fn main() {
+    #[allow(unreachable_code)]
+    $0g();
+}
+            "#,
+            r#"
+fn main() {
+    #[allow(unreachable_code)]
+    {g()};
+}
+            "#,
+        );
     }
 
     #[test]
diff --git a/src/tools/rust-analyzer/crates/load-cargo/Cargo.toml b/src/tools/rust-analyzer/crates/load-cargo/Cargo.toml
index 05412e176b6..48e84a7b25e 100644
--- a/src/tools/rust-analyzer/crates/load-cargo/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/load-cargo/Cargo.toml
@@ -20,6 +20,7 @@ tracing.workspace = true
 
 hir-expand.workspace = true
 ide-db.workspace = true
+paths.workspace = true
 proc-macro-api.workspace = true
 project-model.workspace = true
 span.workspace = true
diff --git a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
index fe680e47fef..79d6fe36b56 100644
--- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
@@ -38,7 +38,7 @@ pub fn load_workspace_at(
     load_config: &LoadCargoConfig,
     progress: &dyn Fn(String),
 ) -> anyhow::Result<(RootDatabase, vfs::Vfs, Option<ProcMacroServer>)> {
-    let root = AbsPathBuf::assert(std::env::current_dir()?.join(root));
+    let root = AbsPathBuf::assert_utf8(std::env::current_dir()?.join(root));
     let root = ProjectManifest::discover_single(&root)?;
     let mut workspace = ProjectWorkspace::load(root, cargo_config, progress)?;
 
@@ -387,7 +387,7 @@ fn expander_to_proc_macro(
     let name = From::from(expander.name());
     let kind = match expander.kind() {
         proc_macro_api::ProcMacroKind::CustomDerive => ProcMacroKind::CustomDerive,
-        proc_macro_api::ProcMacroKind::FuncLike => ProcMacroKind::FuncLike,
+        proc_macro_api::ProcMacroKind::Bang => ProcMacroKind::Bang,
         proc_macro_api::ProcMacroKind::Attr => ProcMacroKind::Attr,
     };
     let disabled = ignored_macros.iter().any(|replace| **replace == name);
diff --git a/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs b/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs
index ac7f0711784..4d5531ae307 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs
@@ -23,7 +23,11 @@ fn benchmark_parse_macro_rules() {
         let _pt = bench("mbe parse macro rules");
         rules
             .values()
-            .map(|it| DeclarativeMacro::parse_macro_rules(it, true, true).rules.len())
+            .map(|it| {
+                DeclarativeMacro::parse_macro_rules(it, |_| span::Edition::CURRENT, true)
+                    .rules
+                    .len()
+            })
             .sum()
     };
     assert_eq!(hash, 1144);
@@ -51,10 +55,12 @@ fn benchmark_expand_macro_rules() {
     assert_eq!(hash, 69413);
 }
 
-fn macro_rules_fixtures() -> FxHashMap<String, DeclarativeMacro<Span>> {
+fn macro_rules_fixtures() -> FxHashMap<String, DeclarativeMacro> {
     macro_rules_fixtures_tt()
         .into_iter()
-        .map(|(id, tt)| (id, DeclarativeMacro::parse_macro_rules(&tt, true, true)))
+        .map(|(id, tt)| {
+            (id, DeclarativeMacro::parse_macro_rules(&tt, |_| span::Edition::CURRENT, true))
+        })
         .collect()
 }
 
@@ -80,7 +86,7 @@ fn macro_rules_fixtures_tt() -> FxHashMap<String, tt::Subtree<Span>> {
 
 /// Generate random invocation fixtures from rules
 fn invocation_fixtures(
-    rules: &FxHashMap<String, DeclarativeMacro<Span>>,
+    rules: &FxHashMap<String, DeclarativeMacro>,
 ) -> Vec<(String, tt::Subtree<Span>)> {
     let mut seed = 123456789;
     let mut res = Vec::new();
@@ -128,11 +134,7 @@ fn invocation_fixtures(
     }
     return res;
 
-    fn collect_from_op(
-        op: &Op<Span>,
-        token_trees: &mut Vec<tt::TokenTree<Span>>,
-        seed: &mut usize,
-    ) {
+    fn collect_from_op(op: &Op, token_trees: &mut Vec<tt::TokenTree<Span>>, seed: &mut usize) {
         return match op {
             Op::Var { kind, .. } => match kind.as_ref() {
                 Some(MetaVarKind::Ident) => token_trees.push(make_ident("foo")),
diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander.rs b/src/tools/rust-analyzer/crates/mbe/src/expander.rs
index 9366048fd95..2f2c0aa6ff5 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/expander.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/expander.rs
@@ -6,22 +6,21 @@ mod matcher;
 mod transcriber;
 
 use rustc_hash::FxHashMap;
+use span::Span;
 use syntax::SmolStr;
-use tt::Span;
 
 use crate::{parser::MetaVarKind, ExpandError, ExpandResult};
 
-pub(crate) fn expand_rules<S: Span>(
-    rules: &[crate::Rule<S>],
-    input: &tt::Subtree<S>,
-    marker: impl Fn(&mut S) + Copy,
-    is_2021: bool,
+pub(crate) fn expand_rules(
+    rules: &[crate::Rule],
+    input: &tt::Subtree<Span>,
+    marker: impl Fn(&mut Span) + Copy,
     new_meta_vars: bool,
-    call_site: S,
-) -> ExpandResult<tt::Subtree<S>> {
-    let mut match_: Option<(matcher::Match<S>, &crate::Rule<S>)> = None;
+    call_site: Span,
+) -> ExpandResult<tt::Subtree<Span>> {
+    let mut match_: Option<(matcher::Match, &crate::Rule)> = None;
     for rule in rules {
-        let new_match = matcher::match_(&rule.lhs, input, is_2021);
+        let new_match = matcher::match_(&rule.lhs, input);
 
         if new_match.err.is_none() {
             // If we find a rule that applies without errors, we're done.
@@ -110,30 +109,24 @@ pub(crate) fn expand_rules<S: Span>(
 /// In other words, `Bindings` is a *multi* mapping from `SmolStr` to
 /// `tt::TokenTree`, where the index to select a particular `TokenTree` among
 /// many is not a plain `usize`, but a `&[usize]`.
-#[derive(Debug, Clone, PartialEq, Eq)]
-struct Bindings<S> {
-    inner: FxHashMap<SmolStr, Binding<S>>,
-}
-
-impl<S> Default for Bindings<S> {
-    fn default() -> Self {
-        Self { inner: Default::default() }
-    }
+#[derive(Debug, Default, Clone, PartialEq, Eq)]
+struct Bindings {
+    inner: FxHashMap<SmolStr, Binding>,
 }
 
 #[derive(Debug, Clone, PartialEq, Eq)]
-enum Binding<S> {
-    Fragment(Fragment<S>),
-    Nested(Vec<Binding<S>>),
+enum Binding {
+    Fragment(Fragment),
+    Nested(Vec<Binding>),
     Empty,
     Missing(MetaVarKind),
 }
 
 #[derive(Debug, Clone, PartialEq, Eq)]
-enum Fragment<S> {
+enum Fragment {
     Empty,
     /// token fragments are just copy-pasted into the output
-    Tokens(tt::TokenTree<S>),
+    Tokens(tt::TokenTree<Span>),
     /// Expr ast fragments are surrounded with `()` on insertion to preserve
     /// precedence. Note that this impl is different from the one currently in
     /// `rustc` -- `rustc` doesn't translate fragments into token trees at all.
@@ -141,7 +134,7 @@ enum Fragment<S> {
     /// At one point in time, we tried to use "fake" delimiters here Ă  la
     /// proc-macro delimiter=none. As we later discovered, "none" delimiters are
     /// tricky to handle in the parser, and rustc doesn't handle those either.
-    Expr(tt::Subtree<S>),
+    Expr(tt::Subtree<Span>),
     /// There are roughly two types of paths: paths in expression context, where a
     /// separator `::` between an identifier and its following generic argument list
     /// is mandatory, and paths in type context, where `::` can be omitted.
@@ -151,5 +144,5 @@ enum Fragment<S> {
     /// and is trasncribed as an expression-context path, verbatim transcription
     /// would cause a syntax error. We need to fix it up just before transcribing;
     /// see `transcriber::fix_up_and_push_path_tt()`.
-    Path(tt::Subtree<S>),
+    Path(tt::Subtree<Span>),
 }
diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs b/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs
index eea92cfba4c..3170834d54f 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs
@@ -62,8 +62,9 @@
 use std::rc::Rc;
 
 use smallvec::{smallvec, SmallVec};
+use span::Span;
 use syntax::SmolStr;
-use tt::{DelimSpan, Span};
+use tt::DelimSpan;
 
 use crate::{
     expander::{Binding, Bindings, ExpandResult, Fragment},
@@ -72,7 +73,7 @@ use crate::{
     ExpandError, MetaTemplate, ValueResult,
 };
 
-impl<S: Span> Bindings<S> {
+impl Bindings {
     fn push_optional(&mut self, name: &SmolStr) {
         self.inner.insert(name.clone(), Binding::Fragment(Fragment::Empty));
     }
@@ -81,14 +82,14 @@ impl<S: Span> Bindings<S> {
         self.inner.insert(name.clone(), Binding::Empty);
     }
 
-    fn bindings(&self) -> impl Iterator<Item = &Binding<S>> {
+    fn bindings(&self) -> impl Iterator<Item = &Binding> {
         self.inner.values()
     }
 }
 
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub(super) struct Match<S> {
-    pub(super) bindings: Bindings<S>,
+#[derive(Clone, Default, Debug, PartialEq, Eq)]
+pub(super) struct Match {
+    pub(super) bindings: Bindings,
     /// We currently just keep the first error and count the rest to compare matches.
     pub(super) err: Option<ExpandError>,
     pub(super) err_count: usize,
@@ -98,19 +99,7 @@ pub(super) struct Match<S> {
     pub(super) bound_count: usize,
 }
 
-impl<S> Default for Match<S> {
-    fn default() -> Self {
-        Self {
-            bindings: Default::default(),
-            err: Default::default(),
-            err_count: Default::default(),
-            unmatched_tts: Default::default(),
-            bound_count: Default::default(),
-        }
-    }
-}
-
-impl<S> Match<S> {
+impl Match {
     fn add_err(&mut self, err: ExpandError) {
         let prev_err = self.err.take();
         self.err = prev_err.or(Some(err));
@@ -119,16 +108,12 @@ impl<S> Match<S> {
 }
 
 /// Matching errors are added to the `Match`.
-pub(super) fn match_<S: Span>(
-    pattern: &MetaTemplate<S>,
-    input: &tt::Subtree<S>,
-    is_2021: bool,
-) -> Match<S> {
-    let mut res = match_loop(pattern, input, is_2021);
+pub(super) fn match_(pattern: &MetaTemplate, input: &tt::Subtree<Span>) -> Match {
+    let mut res = match_loop(pattern, input);
     res.bound_count = count(res.bindings.bindings());
     return res;
 
-    fn count<'a, S: 'a>(bindings: impl Iterator<Item = &'a Binding<S>>) -> usize {
+    fn count<'a>(bindings: impl Iterator<Item = &'a Binding>) -> usize {
         bindings
             .map(|it| match it {
                 Binding::Fragment(_) => 1,
@@ -141,10 +126,10 @@ pub(super) fn match_<S: Span>(
 }
 
 #[derive(Debug, Clone)]
-enum BindingKind<S> {
+enum BindingKind {
     Empty(SmolStr),
     Optional(SmolStr),
-    Fragment(SmolStr, Fragment<S>),
+    Fragment(SmolStr, Fragment),
     Missing(SmolStr, MetaVarKind),
     Nested(usize, usize),
 }
@@ -158,18 +143,13 @@ enum LinkNode<T> {
     Parent { idx: usize, len: usize },
 }
 
-struct BindingsBuilder<S> {
-    nodes: Vec<Vec<LinkNode<Rc<BindingKind<S>>>>>,
+#[derive(Default)]
+struct BindingsBuilder {
+    nodes: Vec<Vec<LinkNode<Rc<BindingKind>>>>,
     nested: Vec<Vec<LinkNode<usize>>>,
 }
 
-impl<S> Default for BindingsBuilder<S> {
-    fn default() -> Self {
-        Self { nodes: Default::default(), nested: Default::default() }
-    }
-}
-
-impl<S: Span> BindingsBuilder<S> {
+impl BindingsBuilder {
     fn alloc(&mut self) -> BindingsIdx {
         let idx = self.nodes.len();
         self.nodes.push(Vec::new());
@@ -206,7 +186,7 @@ impl<S: Span> BindingsBuilder<S> {
         self.nodes[idx.0].push(LinkNode::Node(Rc::new(BindingKind::Optional(var.clone()))));
     }
 
-    fn push_fragment(&mut self, idx: &mut BindingsIdx, var: &SmolStr, fragment: Fragment<S>) {
+    fn push_fragment(&mut self, idx: &mut BindingsIdx, var: &SmolStr, fragment: Fragment) {
         self.nodes[idx.0]
             .push(LinkNode::Node(Rc::new(BindingKind::Fragment(var.clone(), fragment))));
     }
@@ -227,11 +207,11 @@ impl<S: Span> BindingsBuilder<S> {
         idx.0 = new_idx;
     }
 
-    fn build(self, idx: &BindingsIdx) -> Bindings<S> {
+    fn build(self, idx: &BindingsIdx) -> Bindings {
         self.build_inner(&self.nodes[idx.0])
     }
 
-    fn build_inner(&self, link_nodes: &[LinkNode<Rc<BindingKind<S>>>]) -> Bindings<S> {
+    fn build_inner(&self, link_nodes: &[LinkNode<Rc<BindingKind>>]) -> Bindings {
         let mut bindings = Bindings::default();
         let mut nodes = Vec::new();
         self.collect_nodes(link_nodes, &mut nodes);
@@ -281,7 +261,7 @@ impl<S: Span> BindingsBuilder<S> {
         &'a self,
         id: usize,
         len: usize,
-        nested_refs: &mut Vec<&'a [LinkNode<Rc<BindingKind<S>>>]>,
+        nested_refs: &mut Vec<&'a [LinkNode<Rc<BindingKind>>]>,
     ) {
         self.nested[id].iter().take(len).for_each(|it| match it {
             LinkNode::Node(id) => nested_refs.push(&self.nodes[*id]),
@@ -289,7 +269,7 @@ impl<S: Span> BindingsBuilder<S> {
         });
     }
 
-    fn collect_nested(&self, idx: usize, nested_idx: usize, nested: &mut Vec<Bindings<S>>) {
+    fn collect_nested(&self, idx: usize, nested_idx: usize, nested: &mut Vec<Bindings>) {
         let last = &self.nodes[idx];
         let mut nested_refs: Vec<&[_]> = Vec::new();
         self.nested[nested_idx].iter().for_each(|it| match *it {
@@ -300,7 +280,7 @@ impl<S: Span> BindingsBuilder<S> {
         nested.extend(nested_refs.into_iter().map(|iter| self.build_inner(iter)));
     }
 
-    fn collect_nodes_ref<'a>(&'a self, id: usize, len: usize, nodes: &mut Vec<&'a BindingKind<S>>) {
+    fn collect_nodes_ref<'a>(&'a self, id: usize, len: usize, nodes: &mut Vec<&'a BindingKind>) {
         self.nodes[id].iter().take(len).for_each(|it| match it {
             LinkNode::Node(it) => nodes.push(it),
             LinkNode::Parent { idx, len } => self.collect_nodes_ref(*idx, *len, nodes),
@@ -309,8 +289,8 @@ impl<S: Span> BindingsBuilder<S> {
 
     fn collect_nodes<'a>(
         &'a self,
-        link_nodes: &'a [LinkNode<Rc<BindingKind<S>>>],
-        nodes: &mut Vec<&'a BindingKind<S>>,
+        link_nodes: &'a [LinkNode<Rc<BindingKind>>],
+        nodes: &mut Vec<&'a BindingKind>,
     ) {
         link_nodes.iter().for_each(|it| match it {
             LinkNode::Node(it) => nodes.push(it),
@@ -320,22 +300,22 @@ impl<S: Span> BindingsBuilder<S> {
 }
 
 #[derive(Debug, Clone)]
-struct MatchState<'t, S> {
+struct MatchState<'t> {
     /// The position of the "dot" in this matcher
-    dot: OpDelimitedIter<'t, S>,
+    dot: OpDelimitedIter<'t>,
 
     /// Token subtree stack
     /// When matching against matchers with nested delimited submatchers (e.g., `pat ( pat ( .. )
     /// pat ) pat`), we need to keep track of the matchers we are descending into. This stack does
     /// that where the bottom of the stack is the outermost matcher.
-    stack: SmallVec<[OpDelimitedIter<'t, S>; 4]>,
+    stack: SmallVec<[OpDelimitedIter<'t>; 4]>,
 
     /// The "parent" matcher position if we are in a repetition. That is, the matcher position just
     /// before we enter the repetition.
-    up: Option<Box<MatchState<'t, S>>>,
+    up: Option<Box<MatchState<'t>>>,
 
     /// The separator if we are in a repetition.
-    sep: Option<Separator<S>>,
+    sep: Option<Separator>,
 
     /// The KleeneOp of this sequence if we are in a repetition.
     sep_kind: Option<RepeatKind>,
@@ -347,7 +327,7 @@ struct MatchState<'t, S> {
     bindings: BindingsIdx,
 
     /// Cached result of meta variable parsing
-    meta_result: Option<(TtIter<'t, S>, ExpandResult<Option<Fragment<S>>>)>,
+    meta_result: Option<(TtIter<'t, Span>, ExpandResult<Option<Fragment>>)>,
 
     /// Is error occurred in this state, will `poised` to "parent"
     is_error: bool,
@@ -372,18 +352,17 @@ struct MatchState<'t, S> {
 /// - `bb_items`: the set of items that are waiting for the black-box parser.
 /// - `error_items`: the set of items in errors, used for error-resilient parsing
 #[inline]
-fn match_loop_inner<'t, S: Span>(
-    src: TtIter<'t, S>,
-    stack: &[TtIter<'t, S>],
-    res: &mut Match<S>,
-    bindings_builder: &mut BindingsBuilder<S>,
-    cur_items: &mut SmallVec<[MatchState<'t, S>; 1]>,
-    bb_items: &mut SmallVec<[MatchState<'t, S>; 1]>,
-    next_items: &mut Vec<MatchState<'t, S>>,
-    eof_items: &mut SmallVec<[MatchState<'t, S>; 1]>,
-    error_items: &mut SmallVec<[MatchState<'t, S>; 1]>,
-    is_2021: bool,
-    delim_span: tt::DelimSpan<S>,
+fn match_loop_inner<'t>(
+    src: TtIter<'t, Span>,
+    stack: &[TtIter<'t, Span>],
+    res: &mut Match,
+    bindings_builder: &mut BindingsBuilder,
+    cur_items: &mut SmallVec<[MatchState<'t>; 1]>,
+    bb_items: &mut SmallVec<[MatchState<'t>; 1]>,
+    next_items: &mut Vec<MatchState<'t>>,
+    eof_items: &mut SmallVec<[MatchState<'t>; 1]>,
+    error_items: &mut SmallVec<[MatchState<'t>; 1]>,
+    delim_span: tt::DelimSpan<Span>,
 ) {
     macro_rules! try_push {
         ($items: expr, $it:expr) => {
@@ -494,7 +473,7 @@ fn match_loop_inner<'t, S: Span>(
             OpDelimited::Op(Op::Var { kind, name, .. }) => {
                 if let &Some(kind) = kind {
                     let mut fork = src.clone();
-                    let match_res = match_meta_var(kind, &mut fork, is_2021, delim_span);
+                    let match_res = match_meta_var(kind, &mut fork, delim_span);
                     match match_res.err {
                         None => {
                             // Some meta variables are optional (e.g. vis)
@@ -607,10 +586,10 @@ fn match_loop_inner<'t, S: Span>(
     }
 }
 
-fn match_loop<S: Span>(pattern: &MetaTemplate<S>, src: &tt::Subtree<S>, is_2021: bool) -> Match<S> {
+fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree<Span>) -> Match {
     let span = src.delimiter.delim_span();
     let mut src = TtIter::new(src);
-    let mut stack: SmallVec<[TtIter<'_, S>; 1]> = SmallVec::new();
+    let mut stack: SmallVec<[TtIter<'_, Span>; 1]> = SmallVec::new();
     let mut res = Match::default();
     let mut error_recover_item = None;
 
@@ -647,7 +626,6 @@ fn match_loop<S: Span>(pattern: &MetaTemplate<S>, src: &tt::Subtree<S>, is_2021:
             &mut next_items,
             &mut eof_items,
             &mut error_items,
-            is_2021,
             span,
         );
         stdx::always!(cur_items.is_empty());
@@ -758,12 +736,11 @@ fn match_loop<S: Span>(pattern: &MetaTemplate<S>, src: &tt::Subtree<S>, is_2021:
     }
 }
 
-fn match_meta_var<S: Span>(
+fn match_meta_var(
     kind: MetaVarKind,
-    input: &mut TtIter<'_, S>,
-    is_2021: bool,
-    delim_span: DelimSpan<S>,
-) -> ExpandResult<Option<Fragment<S>>> {
+    input: &mut TtIter<'_, Span>,
+    delim_span: DelimSpan<Span>,
+) -> ExpandResult<Option<Fragment>> {
     let fragment = match kind {
         MetaVarKind::Path => {
             return input.expect_fragment(parser::PrefixEntryPoint::Path).map(|it| {
@@ -771,8 +748,7 @@ fn match_meta_var<S: Span>(
             });
         }
         MetaVarKind::Ty => parser::PrefixEntryPoint::Ty,
-        MetaVarKind::Pat if is_2021 => parser::PrefixEntryPoint::PatTop,
-        MetaVarKind::Pat => parser::PrefixEntryPoint::Pat,
+        MetaVarKind::Pat => parser::PrefixEntryPoint::PatTop,
         MetaVarKind::PatParam => parser::PrefixEntryPoint::Pat,
         MetaVarKind::Stmt => parser::PrefixEntryPoint::Stmt,
         MetaVarKind::Block => parser::PrefixEntryPoint::Block,
@@ -846,7 +822,7 @@ fn match_meta_var<S: Span>(
     input.expect_fragment(fragment).map(|it| it.map(Fragment::Tokens))
 }
 
-fn collect_vars<S: Span>(collector_fun: &mut impl FnMut(SmolStr), pattern: &MetaTemplate<S>) {
+fn collect_vars(collector_fun: &mut impl FnMut(SmolStr), pattern: &MetaTemplate) {
     for op in pattern.iter() {
         match op {
             Op::Var { name, .. } => collector_fun(name.clone()),
@@ -859,11 +835,11 @@ fn collect_vars<S: Span>(collector_fun: &mut impl FnMut(SmolStr), pattern: &Meta
         }
     }
 }
-impl<S: Span> MetaTemplate<S> {
-    fn iter_delimited_with(&self, delimiter: tt::Delimiter<S>) -> OpDelimitedIter<'_, S> {
+impl MetaTemplate {
+    fn iter_delimited_with(&self, delimiter: tt::Delimiter<Span>) -> OpDelimitedIter<'_> {
         OpDelimitedIter { inner: &self.0, idx: 0, delimited: delimiter }
     }
-    fn iter_delimited(&self, span: tt::DelimSpan<S>) -> OpDelimitedIter<'_, S> {
+    fn iter_delimited(&self, span: tt::DelimSpan<Span>) -> OpDelimitedIter<'_> {
         OpDelimitedIter {
             inner: &self.0,
             idx: 0,
@@ -873,27 +849,27 @@ impl<S: Span> MetaTemplate<S> {
 }
 
 #[derive(Debug, Clone, Copy)]
-enum OpDelimited<'a, S> {
-    Op(&'a Op<S>),
+enum OpDelimited<'a> {
+    Op(&'a Op),
     Open,
     Close,
 }
 
 #[derive(Debug, Clone, Copy)]
-struct OpDelimitedIter<'a, S> {
-    inner: &'a [Op<S>],
-    delimited: tt::Delimiter<S>,
+struct OpDelimitedIter<'a> {
+    inner: &'a [Op],
+    delimited: tt::Delimiter<Span>,
     idx: usize,
 }
 
-impl<'a, S: Span> OpDelimitedIter<'a, S> {
+impl<'a> OpDelimitedIter<'a> {
     fn is_eof(&self) -> bool {
         let len = self.inner.len()
             + if self.delimited.kind != tt::DelimiterKind::Invisible { 2 } else { 0 };
         self.idx >= len
     }
 
-    fn peek(&self) -> Option<OpDelimited<'a, S>> {
+    fn peek(&self) -> Option<OpDelimited<'a>> {
         match self.delimited.kind {
             tt::DelimiterKind::Invisible => self.inner.get(self.idx).map(OpDelimited::Op),
             _ => match self.idx {
@@ -909,8 +885,8 @@ impl<'a, S: Span> OpDelimitedIter<'a, S> {
     }
 }
 
-impl<'a, S: Span> Iterator for OpDelimitedIter<'a, S> {
-    type Item = OpDelimited<'a, S>;
+impl<'a> Iterator for OpDelimitedIter<'a> {
+    type Item = OpDelimited<'a>;
 
     fn next(&mut self) -> Option<Self::Item> {
         let res = self.peek();
@@ -926,8 +902,8 @@ impl<'a, S: Span> Iterator for OpDelimitedIter<'a, S> {
     }
 }
 
-impl<S: Span> TtIter<'_, S> {
-    fn expect_separator(&mut self, separator: &Separator<S>) -> bool {
+impl TtIter<'_, Span> {
+    fn expect_separator(&mut self, separator: &Separator) -> bool {
         let mut fork = self.clone();
         let ok = match separator {
             Separator::Ident(lhs) => match fork.expect_ident_or_underscore() {
@@ -957,7 +933,7 @@ impl<S: Span> TtIter<'_, S> {
         ok
     }
 
-    fn expect_tt(&mut self) -> Result<tt::TokenTree<S>, ()> {
+    fn expect_tt(&mut self) -> Result<tt::TokenTree<Span>, ()> {
         if let Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) = self.peek_n(0) {
             if punct.char == '\'' {
                 self.expect_lifetime()
@@ -976,7 +952,7 @@ impl<S: Span> TtIter<'_, S> {
         }
     }
 
-    fn expect_lifetime(&mut self) -> Result<tt::TokenTree<S>, ()> {
+    fn expect_lifetime(&mut self) -> Result<tt::TokenTree<Span>, ()> {
         let punct = self.expect_single_punct()?;
         if punct.char != '\'' {
             return Err(());
@@ -997,7 +973,7 @@ impl<S: Span> TtIter<'_, S> {
         .into())
     }
 
-    fn eat_char(&mut self, c: char) -> Option<tt::TokenTree<S>> {
+    fn eat_char(&mut self, c: char) -> Option<tt::TokenTree<Span>> {
         let mut fork = self.clone();
         match fork.expect_char(c) {
             Ok(_) => {
diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs
index 6d3055da286..5e6e45f1521 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs
@@ -1,8 +1,9 @@
 //! Transcriber takes a template, like `fn $ident() {}`, a set of bindings like
 //! `$ident => foo`, interpolates variables in the template, to get `fn foo() {}`
 
+use span::Span;
 use syntax::SmolStr;
-use tt::{Delimiter, Span};
+use tt::Delimiter;
 
 use crate::{
     expander::{Binding, Bindings, Fragment},
@@ -10,8 +11,8 @@ use crate::{
     CountError, ExpandError, ExpandResult, MetaTemplate,
 };
 
-impl<S: Span> Bindings<S> {
-    fn get(&self, name: &str) -> Result<&Binding<S>, ExpandError> {
+impl Bindings {
+    fn get(&self, name: &str) -> Result<&Binding, ExpandError> {
         match self.inner.get(name) {
             Some(binding) => Ok(binding),
             None => Err(ExpandError::UnresolvedBinding(Box::new(Box::from(name)))),
@@ -21,10 +22,10 @@ impl<S: Span> Bindings<S> {
     fn get_fragment(
         &self,
         name: &str,
-        mut span: S,
+        mut span: Span,
         nesting: &mut [NestingState],
-        marker: impl Fn(&mut S),
-    ) -> Result<Fragment<S>, ExpandError> {
+        marker: impl Fn(&mut Span),
+    ) -> Result<Fragment, ExpandError> {
         macro_rules! binding_err {
             ($($arg:tt)*) => { ExpandError::binding_error(format!($($arg)*)) };
         }
@@ -134,15 +135,15 @@ impl<S: Span> Bindings<S> {
     }
 }
 
-pub(super) fn transcribe<S: Span>(
-    template: &MetaTemplate<S>,
-    bindings: &Bindings<S>,
-    marker: impl Fn(&mut S) + Copy,
+pub(super) fn transcribe(
+    template: &MetaTemplate,
+    bindings: &Bindings,
+    marker: impl Fn(&mut Span) + Copy,
     new_meta_vars: bool,
-    call_site: S,
-) -> ExpandResult<tt::Subtree<S>> {
+    call_site: Span,
+) -> ExpandResult<tt::Subtree<Span>> {
     let mut ctx = ExpandCtx { bindings, nesting: Vec::new(), new_meta_vars, call_site };
-    let mut arena: Vec<tt::TokenTree<S>> = Vec::new();
+    let mut arena: Vec<tt::TokenTree<Span>> = Vec::new();
     expand_subtree(&mut ctx, template, None, &mut arena, marker)
 }
 
@@ -158,20 +159,20 @@ struct NestingState {
 }
 
 #[derive(Debug)]
-struct ExpandCtx<'a, S> {
-    bindings: &'a Bindings<S>,
+struct ExpandCtx<'a> {
+    bindings: &'a Bindings,
     nesting: Vec<NestingState>,
     new_meta_vars: bool,
-    call_site: S,
+    call_site: Span,
 }
 
-fn expand_subtree<S: Span>(
-    ctx: &mut ExpandCtx<'_, S>,
-    template: &MetaTemplate<S>,
-    delimiter: Option<Delimiter<S>>,
-    arena: &mut Vec<tt::TokenTree<S>>,
-    marker: impl Fn(&mut S) + Copy,
-) -> ExpandResult<tt::Subtree<S>> {
+fn expand_subtree(
+    ctx: &mut ExpandCtx<'_>,
+    template: &MetaTemplate,
+    delimiter: Option<Delimiter<Span>>,
+    arena: &mut Vec<tt::TokenTree<Span>>,
+    marker: impl Fn(&mut Span) + Copy,
+) -> ExpandResult<tt::Subtree<Span>> {
     // remember how many elements are in the arena now - when returning, we want to drain exactly how many elements we added. This way, the recursive uses of the arena get their own "view" of the arena, but will reuse the allocation
     let start_elements = arena.len();
     let mut err = None;
@@ -332,12 +333,12 @@ fn expand_subtree<S: Span>(
     }
 }
 
-fn expand_var<S: Span>(
-    ctx: &mut ExpandCtx<'_, S>,
+fn expand_var(
+    ctx: &mut ExpandCtx<'_>,
     v: &SmolStr,
-    id: S,
-    marker: impl Fn(&mut S),
-) -> ExpandResult<Fragment<S>> {
+    id: Span,
+    marker: impl Fn(&mut Span),
+) -> ExpandResult<Fragment> {
     // We already handle $crate case in mbe parser
     debug_assert!(v != "crate");
 
@@ -378,15 +379,15 @@ fn expand_var<S: Span>(
     }
 }
 
-fn expand_repeat<S: Span>(
-    ctx: &mut ExpandCtx<'_, S>,
-    template: &MetaTemplate<S>,
+fn expand_repeat(
+    ctx: &mut ExpandCtx<'_>,
+    template: &MetaTemplate,
     kind: RepeatKind,
-    separator: &Option<Separator<S>>,
-    arena: &mut Vec<tt::TokenTree<S>>,
-    marker: impl Fn(&mut S) + Copy,
-) -> ExpandResult<Fragment<S>> {
-    let mut buf: Vec<tt::TokenTree<S>> = Vec::new();
+    separator: &Option<Separator>,
+    arena: &mut Vec<tt::TokenTree<Span>>,
+    marker: impl Fn(&mut Span) + Copy,
+) -> ExpandResult<Fragment> {
+    let mut buf: Vec<tt::TokenTree<Span>> = Vec::new();
     ctx.nesting.push(NestingState { idx: 0, at_end: false, hit: false });
     // Dirty hack to make macro-expansion terminate.
     // This should be replaced by a proper macro-by-example implementation
@@ -478,11 +479,7 @@ fn expand_repeat<S: Span>(
     ExpandResult { value: Fragment::Tokens(tt), err }
 }
 
-fn push_fragment<S: Span>(
-    ctx: &ExpandCtx<'_, S>,
-    buf: &mut Vec<tt::TokenTree<S>>,
-    fragment: Fragment<S>,
-) {
+fn push_fragment(ctx: &ExpandCtx<'_>, buf: &mut Vec<tt::TokenTree<Span>>, fragment: Fragment) {
     match fragment {
         Fragment::Tokens(tt::TokenTree::Subtree(tt)) => push_subtree(buf, tt),
         Fragment::Expr(sub) => {
@@ -494,7 +491,7 @@ fn push_fragment<S: Span>(
     }
 }
 
-fn push_subtree<S>(buf: &mut Vec<tt::TokenTree<S>>, tt: tt::Subtree<S>) {
+fn push_subtree(buf: &mut Vec<tt::TokenTree<Span>>, tt: tt::Subtree<Span>) {
     match tt.delimiter.kind {
         tt::DelimiterKind::Invisible => buf.extend(Vec::from(tt.token_trees)),
         _ => buf.push(tt.into()),
@@ -504,10 +501,10 @@ fn push_subtree<S>(buf: &mut Vec<tt::TokenTree<S>>, tt: tt::Subtree<S>) {
 /// Inserts the path separator `::` between an identifier and its following generic
 /// argument list, and then pushes into the buffer. See [`Fragment::Path`] for why
 /// we need this fixup.
-fn fix_up_and_push_path_tt<S: Span>(
-    ctx: &ExpandCtx<'_, S>,
-    buf: &mut Vec<tt::TokenTree<S>>,
-    subtree: tt::Subtree<S>,
+fn fix_up_and_push_path_tt(
+    ctx: &ExpandCtx<'_>,
+    buf: &mut Vec<tt::TokenTree<Span>>,
+    subtree: tt::Subtree<Span>,
 ) {
     stdx::always!(matches!(subtree.delimiter.kind, tt::DelimiterKind::Invisible));
     let mut prev_was_ident = false;
@@ -546,11 +543,7 @@ fn fix_up_and_push_path_tt<S: Span>(
 
 /// Handles `${count(t, depth)}`. `our_depth` is the recursion depth and `count_depth` is the depth
 /// defined by the metavar expression.
-fn count<S>(
-    binding: &Binding<S>,
-    depth_curr: usize,
-    depth_max: usize,
-) -> Result<usize, CountError> {
+fn count(binding: &Binding, depth_curr: usize, depth_max: usize) -> Result<usize, CountError> {
     match binding {
         Binding::Nested(bs) => {
             if depth_curr == depth_max {
@@ -564,8 +557,8 @@ fn count<S>(
     }
 }
 
-fn count_old<S>(
-    binding: &Binding<S>,
+fn count_old(
+    binding: &Binding,
     our_depth: usize,
     count_depth: Option<usize>,
 ) -> Result<usize, CountError> {
diff --git a/src/tools/rust-analyzer/crates/mbe/src/lib.rs b/src/tools/rust-analyzer/crates/mbe/src/lib.rs
index 62fdce36892..3a853512660 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/lib.rs
@@ -17,8 +17,8 @@ mod tt_iter;
 #[cfg(test)]
 mod benchmark;
 
+use span::{Edition, Span, SyntaxContextId};
 use stdx::impl_from;
-use tt::Span;
 
 use std::fmt;
 
@@ -127,32 +127,29 @@ impl fmt::Display for CountError {
 /// `tt::TokenTree`, but there's a crucial difference: in macro rules, `$ident`
 /// and `$()*` have special meaning (see `Var` and `Repeat` data structures)
 #[derive(Clone, Debug, PartialEq, Eq)]
-pub struct DeclarativeMacro<S> {
-    rules: Box<[Rule<S>]>,
-    // This is used for correctly determining the behavior of the pat fragment
-    // FIXME: This should be tracked by hygiene of the fragment identifier!
-    is_2021: bool,
+pub struct DeclarativeMacro {
+    rules: Box<[Rule]>,
     err: Option<Box<ParseError>>,
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
-struct Rule<S> {
-    lhs: MetaTemplate<S>,
-    rhs: MetaTemplate<S>,
+struct Rule {
+    lhs: MetaTemplate,
+    rhs: MetaTemplate,
 }
 
-impl<S: Span> DeclarativeMacro<S> {
-    pub fn from_err(err: ParseError, is_2021: bool) -> DeclarativeMacro<S> {
-        DeclarativeMacro { rules: Box::default(), is_2021, err: Some(Box::new(err)) }
+impl DeclarativeMacro {
+    pub fn from_err(err: ParseError) -> DeclarativeMacro {
+        DeclarativeMacro { rules: Box::default(), err: Some(Box::new(err)) }
     }
 
     /// The old, `macro_rules! m {}` flavor.
     pub fn parse_macro_rules(
-        tt: &tt::Subtree<S>,
-        is_2021: bool,
+        tt: &tt::Subtree<Span>,
+        edition: impl Copy + Fn(SyntaxContextId) -> Edition,
         // FIXME: Remove this once we drop support for rust 1.76 (defaults to true then)
         new_meta_vars: bool,
-    ) -> DeclarativeMacro<S> {
+    ) -> DeclarativeMacro {
         // Note: this parsing can be implemented using mbe machinery itself, by
         // matching against `$($lhs:tt => $rhs:tt);*` pattern, but implementing
         // manually seems easier.
@@ -161,7 +158,7 @@ impl<S: Span> DeclarativeMacro<S> {
         let mut err = None;
 
         while src.len() > 0 {
-            let rule = match Rule::parse(&mut src, true, new_meta_vars) {
+            let rule = match Rule::parse(edition, &mut src, true, new_meta_vars) {
                 Ok(it) => it,
                 Err(e) => {
                     err = Some(Box::new(e));
@@ -184,16 +181,16 @@ impl<S: Span> DeclarativeMacro<S> {
             }
         }
 
-        DeclarativeMacro { rules: rules.into_boxed_slice(), is_2021, err }
+        DeclarativeMacro { rules: rules.into_boxed_slice(), err }
     }
 
     /// The new, unstable `macro m {}` flavor.
     pub fn parse_macro2(
-        tt: &tt::Subtree<S>,
-        is_2021: bool,
+        tt: &tt::Subtree<Span>,
+        edition: impl Copy + Fn(SyntaxContextId) -> Edition,
         // FIXME: Remove this once we drop support for rust 1.76 (defaults to true then)
         new_meta_vars: bool,
-    ) -> DeclarativeMacro<S> {
+    ) -> DeclarativeMacro {
         let mut src = TtIter::new(tt);
         let mut rules = Vec::new();
         let mut err = None;
@@ -201,7 +198,7 @@ impl<S: Span> DeclarativeMacro<S> {
         if tt::DelimiterKind::Brace == tt.delimiter.kind {
             cov_mark::hit!(parse_macro_def_rules);
             while src.len() > 0 {
-                let rule = match Rule::parse(&mut src, true, new_meta_vars) {
+                let rule = match Rule::parse(edition, &mut src, true, new_meta_vars) {
                     Ok(it) => it,
                     Err(e) => {
                         err = Some(Box::new(e));
@@ -220,7 +217,7 @@ impl<S: Span> DeclarativeMacro<S> {
             }
         } else {
             cov_mark::hit!(parse_macro_def_simple);
-            match Rule::parse(&mut src, false, new_meta_vars) {
+            match Rule::parse(edition, &mut src, false, new_meta_vars) {
                 Ok(rule) => {
                     if src.len() != 0 {
                         err = Some(Box::new(ParseError::expected("remaining tokens in macro def")));
@@ -240,7 +237,7 @@ impl<S: Span> DeclarativeMacro<S> {
             }
         }
 
-        DeclarativeMacro { rules: rules.into_boxed_slice(), is_2021, err }
+        DeclarativeMacro { rules: rules.into_boxed_slice(), err }
     }
 
     pub fn err(&self) -> Option<&ParseError> {
@@ -249,18 +246,19 @@ impl<S: Span> DeclarativeMacro<S> {
 
     pub fn expand(
         &self,
-        tt: &tt::Subtree<S>,
-        marker: impl Fn(&mut S) + Copy,
+        tt: &tt::Subtree<Span>,
+        marker: impl Fn(&mut Span) + Copy,
         new_meta_vars: bool,
-        call_site: S,
-    ) -> ExpandResult<tt::Subtree<S>> {
-        expander::expand_rules(&self.rules, tt, marker, self.is_2021, new_meta_vars, call_site)
+        call_site: Span,
+    ) -> ExpandResult<tt::Subtree<Span>> {
+        expander::expand_rules(&self.rules, tt, marker, new_meta_vars, call_site)
     }
 }
 
-impl<S: Span> Rule<S> {
+impl Rule {
     fn parse(
-        src: &mut TtIter<'_, S>,
+        edition: impl Copy + Fn(SyntaxContextId) -> Edition,
+        src: &mut TtIter<'_, Span>,
         expect_arrow: bool,
         new_meta_vars: bool,
     ) -> Result<Self, ParseError> {
@@ -271,14 +269,14 @@ impl<S: Span> Rule<S> {
         }
         let rhs = src.expect_subtree().map_err(|()| ParseError::expected("expected subtree"))?;
 
-        let lhs = MetaTemplate::parse_pattern(lhs)?;
-        let rhs = MetaTemplate::parse_template(rhs, new_meta_vars)?;
+        let lhs = MetaTemplate::parse_pattern(edition, lhs)?;
+        let rhs = MetaTemplate::parse_template(edition, rhs, new_meta_vars)?;
 
         Ok(crate::Rule { lhs, rhs })
     }
 }
 
-fn validate<S: Span>(pattern: &MetaTemplate<S>) -> Result<(), ParseError> {
+fn validate(pattern: &MetaTemplate) -> Result<(), ParseError> {
     for op in pattern.iter() {
         match op {
             Op::Subtree { tokens, .. } => validate(tokens)?,
diff --git a/src/tools/rust-analyzer/crates/mbe/src/parser.rs b/src/tools/rust-analyzer/crates/mbe/src/parser.rs
index afdbbef2314..eaf2fd8c273 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/parser.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/parser.rs
@@ -2,8 +2,8 @@
 //! trees.
 
 use smallvec::{smallvec, SmallVec};
+use span::{Edition, Span, SyntaxContextId};
 use syntax::SmolStr;
-use tt::Span;
 
 use crate::{tt_iter::TtIter, ParseError};
 
@@ -21,30 +21,39 @@ use crate::{tt_iter::TtIter, ParseError};
 /// Stuff to the right is a [`MetaTemplate`] template which is used to produce
 /// output.
 #[derive(Clone, Debug, PartialEq, Eq)]
-pub(crate) struct MetaTemplate<S>(pub(crate) Box<[Op<S>]>);
+pub(crate) struct MetaTemplate(pub(crate) Box<[Op]>);
 
-impl<S: Span> MetaTemplate<S> {
-    pub(crate) fn parse_pattern(pattern: &tt::Subtree<S>) -> Result<Self, ParseError> {
-        MetaTemplate::parse(pattern, Mode::Pattern, false)
+impl MetaTemplate {
+    pub(crate) fn parse_pattern(
+        edition: impl Copy + Fn(SyntaxContextId) -> Edition,
+        pattern: &tt::Subtree<Span>,
+    ) -> Result<Self, ParseError> {
+        MetaTemplate::parse(edition, pattern, Mode::Pattern, false)
     }
 
     pub(crate) fn parse_template(
-        template: &tt::Subtree<S>,
+        edition: impl Copy + Fn(SyntaxContextId) -> Edition,
+        template: &tt::Subtree<Span>,
         new_meta_vars: bool,
     ) -> Result<Self, ParseError> {
-        MetaTemplate::parse(template, Mode::Template, new_meta_vars)
+        MetaTemplate::parse(edition, template, Mode::Template, new_meta_vars)
     }
 
-    pub(crate) fn iter(&self) -> impl Iterator<Item = &Op<S>> {
+    pub(crate) fn iter(&self) -> impl Iterator<Item = &Op> {
         self.0.iter()
     }
 
-    fn parse(tt: &tt::Subtree<S>, mode: Mode, new_meta_vars: bool) -> Result<Self, ParseError> {
+    fn parse(
+        edition: impl Copy + Fn(SyntaxContextId) -> Edition,
+        tt: &tt::Subtree<Span>,
+        mode: Mode,
+        new_meta_vars: bool,
+    ) -> Result<Self, ParseError> {
         let mut src = TtIter::new(tt);
 
         let mut res = Vec::new();
         while let Some(first) = src.peek_n(0) {
-            let op = next_op(first, &mut src, mode, new_meta_vars)?;
+            let op = next_op(edition, first, &mut src, mode, new_meta_vars)?;
             res.push(op);
         }
 
@@ -53,15 +62,15 @@ impl<S: Span> MetaTemplate<S> {
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
-pub(crate) enum Op<S> {
+pub(crate) enum Op {
     Var {
         name: SmolStr,
         kind: Option<MetaVarKind>,
-        id: S,
+        id: Span,
     },
     Ignore {
         name: SmolStr,
-        id: S,
+        id: Span,
     },
     Index {
         depth: usize,
@@ -75,17 +84,17 @@ pub(crate) enum Op<S> {
         depth: Option<usize>,
     },
     Repeat {
-        tokens: MetaTemplate<S>,
+        tokens: MetaTemplate,
         kind: RepeatKind,
-        separator: Option<Separator<S>>,
+        separator: Option<Separator>,
     },
     Subtree {
-        tokens: MetaTemplate<S>,
-        delimiter: tt::Delimiter<S>,
+        tokens: MetaTemplate,
+        delimiter: tt::Delimiter<Span>,
     },
-    Literal(tt::Literal<S>),
-    Punct(SmallVec<[tt::Punct<S>; 3]>),
-    Ident(tt::Ident<S>),
+    Literal(tt::Literal<Span>),
+    Punct(SmallVec<[tt::Punct<Span>; 3]>),
+    Ident(tt::Ident<Span>),
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -114,15 +123,15 @@ pub(crate) enum MetaVarKind {
 }
 
 #[derive(Clone, Debug, Eq)]
-pub(crate) enum Separator<S> {
-    Literal(tt::Literal<S>),
-    Ident(tt::Ident<S>),
-    Puncts(SmallVec<[tt::Punct<S>; 3]>),
+pub(crate) enum Separator {
+    Literal(tt::Literal<Span>),
+    Ident(tt::Ident<Span>),
+    Puncts(SmallVec<[tt::Punct<Span>; 3]>),
 }
 
 // Note that when we compare a Separator, we just care about its textual value.
-impl<S> PartialEq for Separator<S> {
-    fn eq(&self, other: &Separator<S>) -> bool {
+impl PartialEq for Separator {
+    fn eq(&self, other: &Separator) -> bool {
         use Separator::*;
 
         match (self, other) {
@@ -144,12 +153,13 @@ enum Mode {
     Template,
 }
 
-fn next_op<S: Span>(
-    first_peeked: &tt::TokenTree<S>,
-    src: &mut TtIter<'_, S>,
+fn next_op(
+    edition: impl Copy + Fn(SyntaxContextId) -> Edition,
+    first_peeked: &tt::TokenTree<Span>,
+    src: &mut TtIter<'_, Span>,
     mode: Mode,
     new_meta_vars: bool,
-) -> Result<Op<S>, ParseError> {
+) -> Result<Op, ParseError> {
     let res = match first_peeked {
         tt::TokenTree::Leaf(tt::Leaf::Punct(p @ tt::Punct { char: '$', .. })) => {
             src.next().expect("first token already peeked");
@@ -162,7 +172,7 @@ fn next_op<S: Span>(
                 tt::TokenTree::Subtree(subtree) => match subtree.delimiter.kind {
                     tt::DelimiterKind::Parenthesis => {
                         let (separator, kind) = parse_repeat(src)?;
-                        let tokens = MetaTemplate::parse(subtree, mode, new_meta_vars)?;
+                        let tokens = MetaTemplate::parse(edition, subtree, mode, new_meta_vars)?;
                         Op::Repeat { tokens, separator, kind }
                     }
                     tt::DelimiterKind::Brace => match mode {
@@ -189,13 +199,13 @@ fn next_op<S: Span>(
                         Op::Ident(tt::Ident { text: "$crate".into(), span: ident.span })
                     }
                     tt::Leaf::Ident(ident) => {
-                        let kind = eat_fragment_kind(src, mode)?;
+                        let kind = eat_fragment_kind(edition, src, mode)?;
                         let name = ident.text.clone();
                         let id = ident.span;
                         Op::Var { name, kind, id }
                     }
                     tt::Leaf::Literal(lit) if is_boolean_literal(lit) => {
-                        let kind = eat_fragment_kind(src, mode)?;
+                        let kind = eat_fragment_kind(edition, src, mode)?;
                         let name = lit.text.clone();
                         let id = lit.span;
                         Op::Var { name, kind, id }
@@ -233,15 +243,16 @@ fn next_op<S: Span>(
 
         tt::TokenTree::Subtree(subtree) => {
             src.next().expect("first token already peeked");
-            let tokens = MetaTemplate::parse(subtree, mode, new_meta_vars)?;
+            let tokens = MetaTemplate::parse(edition, subtree, mode, new_meta_vars)?;
             Op::Subtree { tokens, delimiter: subtree.delimiter }
         }
     };
     Ok(res)
 }
 
-fn eat_fragment_kind<S: Span>(
-    src: &mut TtIter<'_, S>,
+fn eat_fragment_kind(
+    edition: impl Copy + Fn(SyntaxContextId) -> Edition,
+    src: &mut TtIter<'_, Span>,
     mode: Mode,
 ) -> Result<Option<MetaVarKind>, ParseError> {
     if let Mode::Pattern = mode {
@@ -252,7 +263,10 @@ fn eat_fragment_kind<S: Span>(
         let kind = match ident.text.as_str() {
             "path" => MetaVarKind::Path,
             "ty" => MetaVarKind::Ty,
-            "pat" => MetaVarKind::Pat,
+            "pat" => match edition(ident.span.ctx) {
+                Edition::Edition2015 | Edition::Edition2018 => MetaVarKind::PatParam,
+                Edition::Edition2021 | Edition::Edition2024 => MetaVarKind::Pat,
+            },
             "pat_param" => MetaVarKind::PatParam,
             "stmt" => MetaVarKind::Stmt,
             "block" => MetaVarKind::Block,
@@ -271,13 +285,11 @@ fn eat_fragment_kind<S: Span>(
     Ok(None)
 }
 
-fn is_boolean_literal<S>(lit: &tt::Literal<S>) -> bool {
+fn is_boolean_literal(lit: &tt::Literal<Span>) -> bool {
     matches!(lit.text.as_str(), "true" | "false")
 }
 
-fn parse_repeat<S: Span>(
-    src: &mut TtIter<'_, S>,
-) -> Result<(Option<Separator<S>>, RepeatKind), ParseError> {
+fn parse_repeat(src: &mut TtIter<'_, Span>) -> Result<(Option<Separator>, RepeatKind), ParseError> {
     let mut separator = Separator::Puncts(SmallVec::new());
     for tt in src {
         let tt = match tt {
@@ -314,7 +326,7 @@ fn parse_repeat<S: Span>(
     Err(ParseError::InvalidRepeat)
 }
 
-fn parse_metavar_expr<S: Span>(new_meta_vars: bool, src: &mut TtIter<'_, S>) -> Result<Op<S>, ()> {
+fn parse_metavar_expr(new_meta_vars: bool, src: &mut TtIter<'_, Span>) -> Result<Op, ()> {
     let func = src.expect_ident()?;
     let args = src.expect_subtree()?;
 
@@ -352,7 +364,7 @@ fn parse_metavar_expr<S: Span>(new_meta_vars: bool, src: &mut TtIter<'_, S>) ->
     Ok(op)
 }
 
-fn parse_depth<S: Span>(src: &mut TtIter<'_, S>) -> Result<usize, ()> {
+fn parse_depth(src: &mut TtIter<'_, Span>) -> Result<usize, ()> {
     if src.len() == 0 {
         Ok(0)
     } else if let tt::Leaf::Literal(lit) = src.expect_literal()? {
@@ -363,7 +375,7 @@ fn parse_depth<S: Span>(src: &mut TtIter<'_, S>) -> Result<usize, ()> {
     }
 }
 
-fn try_eat_comma<S: Span>(src: &mut TtIter<'_, S>) -> bool {
+fn try_eat_comma(src: &mut TtIter<'_, Span>) -> bool {
     if let Some(tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: ',', .. }))) = src.peek_n(0) {
         let _ = src.next();
         return true;
diff --git a/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs b/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs
index 57d6082dd70..c934db6b715 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs
@@ -1,5 +1,7 @@
 //! Conversions between [`SyntaxNode`] and [`tt::TokenTree`].
 
+use std::fmt;
+
 use rustc_hash::{FxHashMap, FxHashSet};
 use span::{SpanAnchor, SpanData, SpanMap};
 use stdx::{never, non_empty_vec::NonEmptyVec};
@@ -9,30 +11,27 @@ use syntax::{
     SyntaxKind::*,
     SyntaxNode, SyntaxToken, SyntaxTreeBuilder, TextRange, TextSize, WalkEvent, T,
 };
-use tt::{
-    buffer::{Cursor, TokenBuffer},
-    Span,
-};
+use tt::buffer::{Cursor, TokenBuffer};
 
 use crate::{to_parser_input::to_parser_input, tt_iter::TtIter};
 
 #[cfg(test)]
 mod tests;
 
-pub trait SpanMapper<S: Span> {
+pub trait SpanMapper<S> {
     fn span_for(&self, range: TextRange) -> S;
 }
 
 impl<S> SpanMapper<SpanData<S>> for SpanMap<S>
 where
-    SpanData<S>: Span,
+    SpanData<S>: Copy,
 {
     fn span_for(&self, range: TextRange) -> SpanData<S> {
         self.span_at(range.start())
     }
 }
 
-impl<S: Span, SM: SpanMapper<S>> SpanMapper<S> for &SM {
+impl<S: Copy, SM: SpanMapper<S>> SpanMapper<S> for &SM {
     fn span_for(&self, range: TextRange) -> S {
         SM::span_for(self, range)
     }
@@ -78,8 +77,7 @@ pub fn syntax_node_to_token_tree<Ctx, SpanMap>(
     span: SpanData<Ctx>,
 ) -> tt::Subtree<SpanData<Ctx>>
 where
-    SpanData<Ctx>: Span,
-    Ctx: Copy,
+    SpanData<Ctx>: Copy + fmt::Debug,
     SpanMap: SpanMapper<SpanData<Ctx>>,
 {
     let mut c = Converter::new(node, map, Default::default(), Default::default(), span);
@@ -98,8 +96,7 @@ pub fn syntax_node_to_token_tree_modified<Ctx, SpanMap>(
 ) -> tt::Subtree<SpanData<Ctx>>
 where
     SpanMap: SpanMapper<SpanData<Ctx>>,
-    SpanData<Ctx>: Span,
-    Ctx: Copy,
+    SpanData<Ctx>: Copy + fmt::Debug,
 {
     let mut c = Converter::new(node, map, append, remove, call_site);
     convert_tokens(&mut c)
@@ -124,8 +121,7 @@ pub fn token_tree_to_syntax_node<Ctx>(
     entry_point: parser::TopEntryPoint,
 ) -> (Parse<SyntaxNode>, SpanMap<Ctx>)
 where
-    SpanData<Ctx>: Span,
-    Ctx: Copy,
+    SpanData<Ctx>: Copy + fmt::Debug,
 {
     let buffer = match tt {
         tt::Subtree {
@@ -161,7 +157,7 @@ pub fn parse_to_token_tree<Ctx>(
     text: &str,
 ) -> Option<tt::Subtree<SpanData<Ctx>>>
 where
-    SpanData<Ctx>: Span,
+    SpanData<Ctx>: Copy + fmt::Debug,
     Ctx: Copy,
 {
     let lexed = parser::LexedStr::new(text);
@@ -175,7 +171,7 @@ where
 /// Convert a string to a `TokenTree`. The passed span will be used for all spans of the produced subtree.
 pub fn parse_to_token_tree_static_span<S>(span: S, text: &str) -> Option<tt::Subtree<S>>
 where
-    S: Span,
+    S: Copy + fmt::Debug,
 {
     let lexed = parser::LexedStr::new(text);
     if lexed.errors().next().is_some() {
@@ -186,11 +182,10 @@ where
 }
 
 /// Split token tree with separate expr: $($e:expr)SEP*
-pub fn parse_exprs_with_sep<S: Span>(
-    tt: &tt::Subtree<S>,
-    sep: char,
-    span: S,
-) -> Vec<tt::Subtree<S>> {
+pub fn parse_exprs_with_sep<S>(tt: &tt::Subtree<S>, sep: char, span: S) -> Vec<tt::Subtree<S>>
+where
+    S: Copy + fmt::Debug,
+{
     if tt.token_trees.is_empty() {
         return Vec::new();
     }
@@ -226,7 +221,8 @@ pub fn parse_exprs_with_sep<S: Span>(
 fn convert_tokens<S, C>(conv: &mut C) -> tt::Subtree<S>
 where
     C: TokenConverter<S>,
-    S: Span,
+    S: Copy + fmt::Debug,
+    C::Token: fmt::Debug,
 {
     let entry = tt::SubtreeBuilder {
         delimiter: tt::Delimiter::invisible_spanned(conv.call_site()),
@@ -485,7 +481,7 @@ struct StaticRawConverter<'a, S> {
     span: S,
 }
 
-trait SrcToken<Ctx, S>: std::fmt::Debug {
+trait SrcToken<Ctx, S> {
     fn kind(&self, ctx: &Ctx) -> SyntaxKind;
 
     fn to_char(&self, ctx: &Ctx) -> Option<char>;
@@ -525,7 +521,7 @@ impl<S, Ctx> SrcToken<RawConverter<'_, Ctx>, S> for usize {
     }
 }
 
-impl<S: Span> SrcToken<StaticRawConverter<'_, S>, S> for usize {
+impl<S: Copy> SrcToken<StaticRawConverter<'_, S>, S> for usize {
     fn kind(&self, ctx: &StaticRawConverter<'_, S>) -> SyntaxKind {
         ctx.lexed.kind(*self)
     }
@@ -541,7 +537,7 @@ impl<S: Span> SrcToken<StaticRawConverter<'_, S>, S> for usize {
 
 impl<Ctx: Copy> TokenConverter<SpanData<Ctx>> for RawConverter<'_, Ctx>
 where
-    SpanData<Ctx>: Span,
+    SpanData<Ctx>: Copy,
 {
     type Token = usize;
 
@@ -584,7 +580,7 @@ where
 
 impl<S> TokenConverter<S> for StaticRawConverter<'_, S>
 where
-    S: Span,
+    S: Copy,
 {
     type Token = usize;
 
@@ -709,7 +705,7 @@ impl<S> SynToken<S> {
     }
 }
 
-impl<SpanMap, S: std::fmt::Debug> SrcToken<Converter<SpanMap, S>, S> for SynToken<S> {
+impl<SpanMap, S> SrcToken<Converter<SpanMap, S>, S> for SynToken<S> {
     fn kind(&self, _ctx: &Converter<SpanMap, S>) -> SyntaxKind {
         match self {
             SynToken::Ordinary(token) => token.kind(),
@@ -748,7 +744,7 @@ impl<SpanMap, S: std::fmt::Debug> SrcToken<Converter<SpanMap, S>, S> for SynToke
 
 impl<S, SpanMap> TokenConverter<S> for Converter<SpanMap, S>
 where
-    S: Span,
+    S: Copy,
     SpanMap: SpanMapper<S>,
 {
     type Token = SynToken<S>;
@@ -828,7 +824,7 @@ where
 
 struct TtTreeSink<'a, Ctx>
 where
-    SpanData<Ctx>: Span,
+    SpanData<Ctx>: Copy,
 {
     buf: String,
     cursor: Cursor<'a, SpanData<Ctx>>,
@@ -839,7 +835,7 @@ where
 
 impl<'a, Ctx> TtTreeSink<'a, Ctx>
 where
-    SpanData<Ctx>: Span,
+    SpanData<Ctx>: Copy,
 {
     fn new(cursor: Cursor<'a, SpanData<Ctx>>) -> Self {
         TtTreeSink {
@@ -871,7 +867,7 @@ fn delim_to_str(d: tt::DelimiterKind, closing: bool) -> Option<&'static str> {
 
 impl<Ctx> TtTreeSink<'_, Ctx>
 where
-    SpanData<Ctx>: Span,
+    SpanData<Ctx>: Copy,
 {
     /// Parses a float literal as if it was a one to two name ref nodes with a dot inbetween.
     /// This occurs when a float literal is used as a field access.
diff --git a/src/tools/rust-analyzer/crates/mbe/src/to_parser_input.rs b/src/tools/rust-analyzer/crates/mbe/src/to_parser_input.rs
index 00a14f04686..3f70149aa5e 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/to_parser_input.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/to_parser_input.rs
@@ -1,11 +1,13 @@
 //! Convert macro-by-example tokens which are specific to macro expansion into a
 //! format that works for our parser.
 
+use std::fmt;
+
 use syntax::{SyntaxKind, SyntaxKind::*, T};
 
-use tt::{buffer::TokenBuffer, Span};
+use tt::buffer::TokenBuffer;
 
-pub(crate) fn to_parser_input<S: Span>(buffer: &TokenBuffer<'_, S>) -> parser::Input {
+pub(crate) fn to_parser_input<S: Copy + fmt::Debug>(buffer: &TokenBuffer<'_, S>) -> parser::Input {
     let mut res = parser::Input::default();
 
     let mut current = buffer.begin();
diff --git a/src/tools/rust-analyzer/crates/mbe/src/tt_iter.rs b/src/tools/rust-analyzer/crates/mbe/src/tt_iter.rs
index f9913cb6f9b..e3d12d87078 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/tt_iter.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/tt_iter.rs
@@ -1,9 +1,10 @@
 //! A "Parser" structure for token trees. We use this when parsing a declarative
 //! macro definition into a list of patterns and templates.
 
+use core::fmt;
+
 use smallvec::{smallvec, SmallVec};
 use syntax::SyntaxKind;
-use tt::Span;
 
 use crate::{to_parser_input::to_parser_input, ExpandError, ExpandResult};
 
@@ -12,7 +13,7 @@ pub(crate) struct TtIter<'a, S> {
     pub(crate) inner: std::slice::Iter<'a, tt::TokenTree<S>>,
 }
 
-impl<'a, S: Span> TtIter<'a, S> {
+impl<'a, S: Copy> TtIter<'a, S> {
     pub(crate) fn new(subtree: &'a tt::Subtree<S>) -> TtIter<'a, S> {
         TtIter { inner: subtree.token_trees.iter() }
     }
@@ -130,7 +131,12 @@ impl<'a, S: Span> TtIter<'a, S> {
             _ => Ok(smallvec![first]),
         }
     }
+    pub(crate) fn peek_n(&self, n: usize) -> Option<&'a tt::TokenTree<S>> {
+        self.inner.as_slice().get(n)
+    }
+}
 
+impl<'a, S: Copy + fmt::Debug> TtIter<'a, S> {
     pub(crate) fn expect_fragment(
         &mut self,
         entry_point: parser::PrefixEntryPoint,
@@ -185,10 +191,6 @@ impl<'a, S: Span> TtIter<'a, S> {
         };
         ExpandResult { value: res, err }
     }
-
-    pub(crate) fn peek_n(&self, n: usize) -> Option<&'a tt::TokenTree<S>> {
-        self.inner.as_slice().get(n)
-    }
 }
 
 impl<'a, S> Iterator for TtIter<'a, S> {
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs
index 72848a1f2b7..54ed5f0ba23 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs
@@ -490,6 +490,18 @@ fn match_expr(p: &mut Parser<'_>) -> CompletedMarker {
     m.complete(p, MATCH_EXPR)
 }
 
+// test_err match_arms_recovery
+// fn foo() {
+//     match () {
+//         _ => (),,
+//         _ => ,
+//         _ => (),
+//          => (),
+//         if true => (),
+//         _ => (),
+//         () if => (),
+//     }
+// }
 pub(crate) fn match_arm_list(p: &mut Parser<'_>) {
     assert!(p.at(T!['{']));
     let m = p.start();
@@ -511,6 +523,10 @@ pub(crate) fn match_arm_list(p: &mut Parser<'_>) {
             error_block(p, "expected match arm");
             continue;
         }
+        if p.at(T![,]) {
+            p.err_and_bump("expected pattern");
+            continue;
+        }
         match_arm(p);
     }
     p.expect(T!['}']);
@@ -544,26 +560,30 @@ fn match_arm(p: &mut Parser<'_>) {
     // }
     attributes::outer_attrs(p);
 
-    patterns::pattern_top_r(p, TokenSet::EMPTY);
+    patterns::pattern_top_r(p, TokenSet::new(&[T![=], T![if]]));
     if p.at(T![if]) {
         match_guard(p);
     }
     p.expect(T![=>]);
-    let blocklike = match expr_stmt(p, None) {
-        Some((_, blocklike)) => blocklike,
-        None => BlockLike::NotBlock,
-    };
-
-    // test match_arms_commas
-    // fn foo() {
-    //     match () {
-    //         _ => (),
-    //         _ => {}
-    //         _ => ()
-    //     }
-    // }
-    if !p.eat(T![,]) && !blocklike.is_block() && !p.at(T!['}']) {
-        p.error("expected `,`");
+    if p.eat(T![,]) {
+        p.error("expected expression");
+    } else {
+        let blocklike = match expr_stmt(p, None) {
+            Some((_, blocklike)) => blocklike,
+            None => BlockLike::NotBlock,
+        };
+
+        // test match_arms_commas
+        // fn foo() {
+        //     match () {
+        //         _ => (),
+        //         _ => {}
+        //         _ => ()
+        //     }
+        // }
+        if !p.eat(T![,]) && !blocklike.is_block() && !p.at(T!['}']) {
+            p.error("expected `,`");
+        }
     }
     m.complete(p, MATCH_ARM);
 }
@@ -579,7 +599,11 @@ fn match_guard(p: &mut Parser<'_>) -> CompletedMarker {
     assert!(p.at(T![if]));
     let m = p.start();
     p.bump(T![if]);
-    expr(p);
+    if p.at(T![=]) {
+        p.error("expected expression");
+    } else {
+        expr(p);
+    }
     m.complete(p, MATCH_GUARD)
 }
 
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0034_match_arms_recovery.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0034_match_arms_recovery.rast
new file mode 100644
index 00000000000..5b191945e45
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0034_match_arms_recovery.rast
@@ -0,0 +1,113 @@
+SOURCE_FILE
+  FN
+    FN_KW "fn"
+    WHITESPACE " "
+    NAME
+      IDENT "foo"
+    PARAM_LIST
+      L_PAREN "("
+      R_PAREN ")"
+    WHITESPACE " "
+    BLOCK_EXPR
+      STMT_LIST
+        L_CURLY "{"
+        WHITESPACE "\n    "
+        MATCH_EXPR
+          MATCH_KW "match"
+          WHITESPACE " "
+          TUPLE_EXPR
+            L_PAREN "("
+            R_PAREN ")"
+          WHITESPACE " "
+          MATCH_ARM_LIST
+            L_CURLY "{"
+            WHITESPACE "\n        "
+            MATCH_ARM
+              WILDCARD_PAT
+                UNDERSCORE "_"
+              WHITESPACE " "
+              FAT_ARROW "=>"
+              WHITESPACE " "
+              TUPLE_EXPR
+                L_PAREN "("
+                R_PAREN ")"
+              COMMA ","
+            ERROR
+              COMMA ","
+            WHITESPACE "\n        "
+            MATCH_ARM
+              WILDCARD_PAT
+                UNDERSCORE "_"
+              WHITESPACE " "
+              FAT_ARROW "=>"
+              WHITESPACE " "
+              COMMA ","
+            WHITESPACE "\n        "
+            MATCH_ARM
+              WILDCARD_PAT
+                UNDERSCORE "_"
+              WHITESPACE " "
+              FAT_ARROW "=>"
+              WHITESPACE " "
+              TUPLE_EXPR
+                L_PAREN "("
+                R_PAREN ")"
+              COMMA ","
+            WHITESPACE "\n         "
+            MATCH_ARM
+              FAT_ARROW "=>"
+              WHITESPACE " "
+              TUPLE_EXPR
+                L_PAREN "("
+                R_PAREN ")"
+              COMMA ","
+            WHITESPACE "\n        "
+            MATCH_ARM
+              MATCH_GUARD
+                IF_KW "if"
+                WHITESPACE " "
+                LITERAL
+                  TRUE_KW "true"
+              WHITESPACE " "
+              FAT_ARROW "=>"
+              WHITESPACE " "
+              TUPLE_EXPR
+                L_PAREN "("
+                R_PAREN ")"
+              COMMA ","
+            WHITESPACE "\n        "
+            MATCH_ARM
+              WILDCARD_PAT
+                UNDERSCORE "_"
+              WHITESPACE " "
+              FAT_ARROW "=>"
+              WHITESPACE " "
+              TUPLE_EXPR
+                L_PAREN "("
+                R_PAREN ")"
+              COMMA ","
+            WHITESPACE "\n        "
+            MATCH_ARM
+              TUPLE_PAT
+                L_PAREN "("
+                R_PAREN ")"
+              WHITESPACE " "
+              MATCH_GUARD
+                IF_KW "if"
+              WHITESPACE " "
+              FAT_ARROW "=>"
+              WHITESPACE " "
+              TUPLE_EXPR
+                L_PAREN "("
+                R_PAREN ")"
+              COMMA ","
+            WHITESPACE "\n    "
+            R_CURLY "}"
+        WHITESPACE "\n"
+        R_CURLY "}"
+  WHITESPACE "\n"
+error 42: expected pattern
+error 58: expected expression
+error 85: expected pattern
+error 100: expected pattern
+error 145: expected expression
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0034_match_arms_recovery.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0034_match_arms_recovery.rs
new file mode 100644
index 00000000000..173103b2e37
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0034_match_arms_recovery.rs
@@ -0,0 +1,11 @@
+fn foo() {
+    match () {
+        _ => (),,
+        _ => ,
+        _ => (),
+         => (),
+        if true => (),
+        _ => (),
+        () if => (),
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/paths/Cargo.toml b/src/tools/rust-analyzer/crates/paths/Cargo.toml
index 3d8752b5a82..59a4ad9a255 100644
--- a/src/tools/rust-analyzer/crates/paths/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/paths/Cargo.toml
@@ -12,10 +12,14 @@ rust-version.workspace = true
 doctest = false
 
 [dependencies]
+camino.workspace = true
 # Adding this dep sadly puts a lot of rust-analyzer crates after the
 # serde-derive crate. Even though we don't activate the derive feature here,
 # someone else in the crate graph certainly does!
 # serde.workspace = true
 
+[features]
+serde1 = ["camino/serde1"]
+
 [lints]
-workspace = true
\ No newline at end of file
+workspace = true
diff --git a/src/tools/rust-analyzer/crates/paths/src/lib.rs b/src/tools/rust-analyzer/crates/paths/src/lib.rs
index a63d251c20d..2d3653401d2 100644
--- a/src/tools/rust-analyzer/crates/paths/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/paths/src/lib.rs
@@ -1,4 +1,4 @@
-//! Thin wrappers around `std::path`, distinguishing between absolute and
+//! Thin wrappers around `std::path`/`camino::path`, distinguishing between absolute and
 //! relative paths.
 
 #![warn(rust_2018_idioms, unused_lifetimes)]
@@ -7,16 +7,24 @@ use std::{
     borrow::Borrow,
     ffi::OsStr,
     fmt, ops,
-    path::{Component, Path, PathBuf},
+    path::{Path, PathBuf},
 };
 
-/// Wrapper around an absolute [`PathBuf`].
-#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
-pub struct AbsPathBuf(PathBuf);
+pub use camino::*;
+
+/// Wrapper around an absolute [`Utf8PathBuf`].
+#[derive(Debug, Clone, Ord, PartialOrd, Eq, Hash)]
+pub struct AbsPathBuf(Utf8PathBuf);
+
+impl From<AbsPathBuf> for Utf8PathBuf {
+    fn from(AbsPathBuf(path_buf): AbsPathBuf) -> Utf8PathBuf {
+        path_buf
+    }
+}
 
 impl From<AbsPathBuf> for PathBuf {
     fn from(AbsPathBuf(path_buf): AbsPathBuf) -> PathBuf {
-        path_buf
+        path_buf.into()
     }
 }
 
@@ -27,9 +35,21 @@ impl ops::Deref for AbsPathBuf {
     }
 }
 
+impl AsRef<Utf8Path> for AbsPathBuf {
+    fn as_ref(&self) -> &Utf8Path {
+        self.0.as_path()
+    }
+}
+
+impl AsRef<OsStr> for AbsPathBuf {
+    fn as_ref(&self) -> &OsStr {
+        self.0.as_ref()
+    }
+}
+
 impl AsRef<Path> for AbsPathBuf {
     fn as_ref(&self) -> &Path {
-        self.0.as_path()
+        self.0.as_ref()
     }
 }
 
@@ -45,26 +65,36 @@ impl Borrow<AbsPath> for AbsPathBuf {
     }
 }
 
+impl TryFrom<Utf8PathBuf> for AbsPathBuf {
+    type Error = Utf8PathBuf;
+    fn try_from(path_buf: Utf8PathBuf) -> Result<AbsPathBuf, Utf8PathBuf> {
+        if !path_buf.is_absolute() {
+            return Err(path_buf);
+        }
+        Ok(AbsPathBuf(path_buf))
+    }
+}
+
 impl TryFrom<PathBuf> for AbsPathBuf {
     type Error = PathBuf;
     fn try_from(path_buf: PathBuf) -> Result<AbsPathBuf, PathBuf> {
         if !path_buf.is_absolute() {
             return Err(path_buf);
         }
-        Ok(AbsPathBuf(path_buf))
+        Ok(AbsPathBuf(Utf8PathBuf::from_path_buf(path_buf)?))
     }
 }
 
 impl TryFrom<&str> for AbsPathBuf {
-    type Error = PathBuf;
-    fn try_from(path: &str) -> Result<AbsPathBuf, PathBuf> {
-        AbsPathBuf::try_from(PathBuf::from(path))
+    type Error = Utf8PathBuf;
+    fn try_from(path: &str) -> Result<AbsPathBuf, Utf8PathBuf> {
+        AbsPathBuf::try_from(Utf8PathBuf::from(path))
     }
 }
 
-impl PartialEq<AbsPath> for AbsPathBuf {
-    fn eq(&self, other: &AbsPath) -> bool {
-        self.as_path() == other
+impl<P: AsRef<Path> + ?Sized> PartialEq<P> for AbsPathBuf {
+    fn eq(&self, other: &P) -> bool {
+        self.0.as_std_path() == other.as_ref()
     }
 }
 
@@ -74,19 +104,31 @@ impl AbsPathBuf {
     /// # Panics
     ///
     /// Panics if `path` is not absolute.
-    pub fn assert(path: PathBuf) -> AbsPathBuf {
+    pub fn assert(path: Utf8PathBuf) -> AbsPathBuf {
         AbsPathBuf::try_from(path)
-            .unwrap_or_else(|path| panic!("expected absolute path, got {}", path.display()))
+            .unwrap_or_else(|path| panic!("expected absolute path, got {}", path))
+    }
+
+    /// Wrap the given absolute path in `AbsPathBuf`
+    ///
+    /// # Panics
+    ///
+    /// Panics if `path` is not absolute.
+    pub fn assert_utf8(path: PathBuf) -> AbsPathBuf {
+        AbsPathBuf::assert(
+            Utf8PathBuf::from_path_buf(path)
+                .unwrap_or_else(|path| panic!("expected utf8 path, got {}", path.display())),
+        )
     }
 
     /// Coerces to an `AbsPath` slice.
     ///
-    /// Equivalent of [`PathBuf::as_path`] for `AbsPathBuf`.
+    /// Equivalent of [`Utf8PathBuf::as_path`] for `AbsPathBuf`.
     pub fn as_path(&self) -> &AbsPath {
         AbsPath::assert(self.0.as_path())
     }
 
-    /// Equivalent of [`PathBuf::pop`] for `AbsPathBuf`.
+    /// Equivalent of [`Utf8PathBuf::pop`] for `AbsPathBuf`.
     ///
     /// Note that this won't remove the root component, so `self` will still be
     /// absolute.
@@ -97,18 +139,36 @@ impl AbsPathBuf {
 
 impl fmt::Display for AbsPathBuf {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(&self.0.display(), f)
+        fmt::Display::fmt(&self.0, f)
     }
 }
 
-/// Wrapper around an absolute [`Path`].
-#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
+/// Wrapper around an absolute [`Utf8Path`].
+#[derive(Debug, Ord, PartialOrd, Eq, Hash)]
 #[repr(transparent)]
-pub struct AbsPath(Path);
+pub struct AbsPath(Utf8Path);
+
+impl<P: AsRef<Path> + ?Sized> PartialEq<P> for AbsPath {
+    fn eq(&self, other: &P) -> bool {
+        self.0.as_std_path() == other.as_ref()
+    }
+}
+
+impl AsRef<Utf8Path> for AbsPath {
+    fn as_ref(&self) -> &Utf8Path {
+        &self.0
+    }
+}
 
 impl AsRef<Path> for AbsPath {
     fn as_ref(&self) -> &Path {
-        &self.0
+        self.0.as_ref()
+    }
+}
+
+impl AsRef<OsStr> for AbsPath {
+    fn as_ref(&self) -> &OsStr {
+        self.0.as_ref()
     }
 }
 
@@ -120,9 +180,9 @@ impl ToOwned for AbsPath {
     }
 }
 
-impl<'a> TryFrom<&'a Path> for &'a AbsPath {
-    type Error = &'a Path;
-    fn try_from(path: &'a Path) -> Result<&'a AbsPath, &'a Path> {
+impl<'a> TryFrom<&'a Utf8Path> for &'a AbsPath {
+    type Error = &'a Utf8Path;
+    fn try_from(path: &'a Utf8Path) -> Result<&'a AbsPath, &'a Utf8Path> {
         if !path.is_absolute() {
             return Err(path);
         }
@@ -136,24 +196,24 @@ impl AbsPath {
     /// # Panics
     ///
     /// Panics if `path` is not absolute.
-    pub fn assert(path: &Path) -> &AbsPath {
+    pub fn assert(path: &Utf8Path) -> &AbsPath {
         assert!(path.is_absolute());
-        unsafe { &*(path as *const Path as *const AbsPath) }
+        unsafe { &*(path as *const Utf8Path as *const AbsPath) }
     }
 
-    /// Equivalent of [`Path::parent`] for `AbsPath`.
+    /// Equivalent of [`Utf8Path::parent`] for `AbsPath`.
     pub fn parent(&self) -> Option<&AbsPath> {
         self.0.parent().map(AbsPath::assert)
     }
 
-    /// Equivalent of [`Path::join`] for `AbsPath` with an additional normalize step afterwards.
-    pub fn absolutize(&self, path: impl AsRef<Path>) -> AbsPathBuf {
+    /// Equivalent of [`Utf8Path::join`] for `AbsPath` with an additional normalize step afterwards.
+    pub fn absolutize(&self, path: impl AsRef<Utf8Path>) -> AbsPathBuf {
         self.join(path).normalize()
     }
 
-    /// Equivalent of [`Path::join`] for `AbsPath`.
-    pub fn join(&self, path: impl AsRef<Path>) -> AbsPathBuf {
-        self.as_ref().join(path).try_into().unwrap()
+    /// Equivalent of [`Utf8Path::join`] for `AbsPath`.
+    pub fn join(&self, path: impl AsRef<Utf8Path>) -> AbsPathBuf {
+        Utf8Path::join(self.as_ref(), path).try_into().unwrap()
     }
 
     /// Normalize the given path:
@@ -172,7 +232,7 @@ impl AbsPath {
         AbsPathBuf(normalize_path(&self.0))
     }
 
-    /// Equivalent of [`Path::to_path_buf`] for `AbsPath`.
+    /// Equivalent of [`Utf8Path::to_path_buf`] for `AbsPath`.
     pub fn to_path_buf(&self) -> AbsPathBuf {
         AbsPathBuf::try_from(self.0.to_path_buf()).unwrap()
     }
@@ -181,7 +241,7 @@ impl AbsPath {
         panic!("We explicitly do not provide canonicalization API, as that is almost always a wrong solution, see #14430")
     }
 
-    /// Equivalent of [`Path::strip_prefix`] for `AbsPath`.
+    /// Equivalent of [`Utf8Path::strip_prefix`] for `AbsPath`.
     ///
     /// Returns a relative path.
     pub fn strip_prefix(&self, base: &AbsPath) -> Option<&RelPath> {
@@ -195,57 +255,61 @@ impl AbsPath {
     }
 
     pub fn name_and_extension(&self) -> Option<(&str, Option<&str>)> {
-        Some((
-            self.file_stem()?.to_str()?,
-            self.extension().and_then(|extension| extension.to_str()),
-        ))
+        Some((self.file_stem()?, self.extension()))
     }
 
     // region:delegate-methods
 
-    // Note that we deliberately don't implement `Deref<Target = Path>` here.
+    // Note that we deliberately don't implement `Deref<Target = Utf8Path>` here.
     //
-    // The problem with `Path` is that it directly exposes convenience IO-ing
-    // methods. For example, `Path::exists` delegates to `fs::metadata`.
+    // The problem with `Utf8Path` is that it directly exposes convenience IO-ing
+    // methods. For example, `Utf8Path::exists` delegates to `fs::metadata`.
     //
     // For `AbsPath`, we want to make sure that this is a POD type, and that all
     // IO goes via `fs`. That way, it becomes easier to mock IO when we need it.
 
-    pub fn file_name(&self) -> Option<&OsStr> {
+    pub fn file_name(&self) -> Option<&str> {
         self.0.file_name()
     }
-    pub fn extension(&self) -> Option<&OsStr> {
+    pub fn extension(&self) -> Option<&str> {
         self.0.extension()
     }
-    pub fn file_stem(&self) -> Option<&OsStr> {
+    pub fn file_stem(&self) -> Option<&str> {
         self.0.file_stem()
     }
     pub fn as_os_str(&self) -> &OsStr {
         self.0.as_os_str()
     }
+    pub fn as_str(&self) -> &str {
+        self.0.as_str()
+    }
     #[deprecated(note = "use Display instead")]
-    pub fn display(&self) -> std::path::Display<'_> {
-        self.0.display()
+    pub fn display(&self) -> ! {
+        unimplemented!()
     }
     #[deprecated(note = "use std::fs::metadata().is_ok() instead")]
-    pub fn exists(&self) -> bool {
-        self.0.exists()
+    pub fn exists(&self) -> ! {
+        unimplemented!()
+    }
+
+    pub fn components(&self) -> Utf8Components<'_> {
+        self.0.components()
     }
     // endregion:delegate-methods
 }
 
 impl fmt::Display for AbsPath {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(&self.0.display(), f)
+        fmt::Display::fmt(&self.0, f)
     }
 }
 
-/// Wrapper around a relative [`PathBuf`].
+/// Wrapper around a relative [`Utf8PathBuf`].
 #[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
-pub struct RelPathBuf(PathBuf);
+pub struct RelPathBuf(Utf8PathBuf);
 
-impl From<RelPathBuf> for PathBuf {
-    fn from(RelPathBuf(path_buf): RelPathBuf) -> PathBuf {
+impl From<RelPathBuf> for Utf8PathBuf {
+    fn from(RelPathBuf(path_buf): RelPathBuf) -> Utf8PathBuf {
         path_buf
     }
 }
@@ -257,15 +321,21 @@ impl ops::Deref for RelPathBuf {
     }
 }
 
+impl AsRef<Utf8Path> for RelPathBuf {
+    fn as_ref(&self) -> &Utf8Path {
+        self.0.as_path()
+    }
+}
+
 impl AsRef<Path> for RelPathBuf {
     fn as_ref(&self) -> &Path {
-        self.0.as_path()
+        self.0.as_ref()
     }
 }
 
-impl TryFrom<PathBuf> for RelPathBuf {
-    type Error = PathBuf;
-    fn try_from(path_buf: PathBuf) -> Result<RelPathBuf, PathBuf> {
+impl TryFrom<Utf8PathBuf> for RelPathBuf {
+    type Error = Utf8PathBuf;
+    fn try_from(path_buf: Utf8PathBuf) -> Result<RelPathBuf, Utf8PathBuf> {
         if !path_buf.is_relative() {
             return Err(path_buf);
         }
@@ -274,65 +344,79 @@ impl TryFrom<PathBuf> for RelPathBuf {
 }
 
 impl TryFrom<&str> for RelPathBuf {
-    type Error = PathBuf;
-    fn try_from(path: &str) -> Result<RelPathBuf, PathBuf> {
-        RelPathBuf::try_from(PathBuf::from(path))
+    type Error = Utf8PathBuf;
+    fn try_from(path: &str) -> Result<RelPathBuf, Utf8PathBuf> {
+        RelPathBuf::try_from(Utf8PathBuf::from(path))
     }
 }
 
 impl RelPathBuf {
     /// Coerces to a `RelPath` slice.
     ///
-    /// Equivalent of [`PathBuf::as_path`] for `RelPathBuf`.
+    /// Equivalent of [`Utf8PathBuf::as_path`] for `RelPathBuf`.
     pub fn as_path(&self) -> &RelPath {
         RelPath::new_unchecked(self.0.as_path())
     }
 }
 
-/// Wrapper around a relative [`Path`].
+/// Wrapper around a relative [`Utf8Path`].
 #[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
 #[repr(transparent)]
-pub struct RelPath(Path);
+pub struct RelPath(Utf8Path);
+
+impl AsRef<Utf8Path> for RelPath {
+    fn as_ref(&self) -> &Utf8Path {
+        &self.0
+    }
+}
 
 impl AsRef<Path> for RelPath {
     fn as_ref(&self) -> &Path {
-        &self.0
+        self.0.as_ref()
     }
 }
 
 impl RelPath {
     /// Creates a new `RelPath` from `path`, without checking if it is relative.
-    pub fn new_unchecked(path: &Path) -> &RelPath {
-        unsafe { &*(path as *const Path as *const RelPath) }
+    pub fn new_unchecked(path: &Utf8Path) -> &RelPath {
+        unsafe { &*(path as *const Utf8Path as *const RelPath) }
     }
 
-    /// Equivalent of [`Path::to_path_buf`] for `RelPath`.
+    /// Equivalent of [`Utf8Path::to_path_buf`] for `RelPath`.
     pub fn to_path_buf(&self) -> RelPathBuf {
         RelPathBuf::try_from(self.0.to_path_buf()).unwrap()
     }
+
+    pub fn as_utf8_path(&self) -> &Utf8Path {
+        self.as_ref()
+    }
+
+    pub fn as_str(&self) -> &str {
+        self.0.as_str()
+    }
 }
 
 /// Taken from <https://github.com/rust-lang/cargo/blob/79c769c3d7b4c2cf6a93781575b7f592ef974255/src/cargo/util/paths.rs#L60-L85>
-fn normalize_path(path: &Path) -> PathBuf {
+fn normalize_path(path: &Utf8Path) -> Utf8PathBuf {
     let mut components = path.components().peekable();
-    let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().copied() {
+    let mut ret = if let Some(c @ Utf8Component::Prefix(..)) = components.peek().copied() {
         components.next();
-        PathBuf::from(c.as_os_str())
+        Utf8PathBuf::from(c.as_str())
     } else {
-        PathBuf::new()
+        Utf8PathBuf::new()
     };
 
     for component in components {
         match component {
-            Component::Prefix(..) => unreachable!(),
-            Component::RootDir => {
-                ret.push(component.as_os_str());
+            Utf8Component::Prefix(..) => unreachable!(),
+            Utf8Component::RootDir => {
+                ret.push(component.as_str());
             }
-            Component::CurDir => {}
-            Component::ParentDir => {
+            Utf8Component::CurDir => {}
+            Utf8Component::ParentDir => {
                 ret.pop();
             }
-            Component::Normal(c) => {
+            Utf8Component::Normal(c) => {
                 ret.push(c);
             }
         }
diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml
index 978ad155609..f30f6a0f23b 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml
@@ -23,7 +23,7 @@ snap = "1.1.0"
 indexmap = "2.1.0"
 
 # local deps
-paths.workspace = true
+paths = { workspace = true, features = ["serde1"] }
 tt.workspace = true
 stdx.workspace = true
 text-size.workspace = true
diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs
index 6b16711a8d8..fd491644648 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs
@@ -35,8 +35,11 @@ pub use version::{read_dylib_info, read_version, RustCInfo};
 #[derive(Copy, Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
 pub enum ProcMacroKind {
     CustomDerive,
-    FuncLike,
     Attr,
+    // This used to be called FuncLike, so that's what the server expects currently.
+    #[serde(alias = "bang")]
+    #[serde(rename(serialize = "FuncLike", deserialize = "FuncLike"))]
+    Bang,
 }
 
 /// A handle to an external process which load dylibs with macros (.so or .dll)
diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs
index aa5aff455fd..ad0e1f187b6 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs
@@ -1,11 +1,9 @@
 //! Defines messages for cross-process message passing based on `ndjson` wire protocol
 pub(crate) mod flat;
 
-use std::{
-    io::{self, BufRead, Write},
-    path::PathBuf,
-};
+use std::io::{self, BufRead, Write};
 
+use paths::Utf8PathBuf;
 use serde::{de::DeserializeOwned, Deserialize, Serialize};
 
 use crate::ProcMacroKind;
@@ -27,7 +25,7 @@ pub const CURRENT_API_VERSION: u32 = RUST_ANALYZER_SPAN_SUPPORT;
 #[derive(Debug, Serialize, Deserialize)]
 pub enum Request {
     /// Since [`NO_VERSION_CHECK_VERSION`]
-    ListMacros { dylib_path: PathBuf },
+    ListMacros { dylib_path: Utf8PathBuf },
     /// Since [`NO_VERSION_CHECK_VERSION`]
     ExpandMacro(Box<ExpandMacro>),
     /// Since [`VERSION_CHECK_VERSION`]
@@ -89,7 +87,7 @@ pub struct ExpandMacro {
     /// Possible attributes for the attribute-like macros.
     pub attributes: Option<FlatTree>,
 
-    pub lib: PathBuf,
+    pub lib: Utf8PathBuf,
 
     /// Environment variables to set during macro expansion.
     pub env: Vec<(String, String)>,
@@ -273,7 +271,7 @@ mod tests {
             macro_body: FlatTree::new(&tt, CURRENT_API_VERSION, &mut span_data_table),
             macro_name: Default::default(),
             attributes: None,
-            lib: std::env::current_dir().unwrap(),
+            lib: Utf8PathBuf::from_path_buf(std::env::current_dir().unwrap()).unwrap(),
             env: Default::default(),
             current_dir: Default::default(),
             has_global_spans: ExpnGlobals {
diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs
index caf9e237fdd..99cdbd930e1 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs
@@ -88,8 +88,6 @@ impl std::fmt::Debug for TokenId {
     }
 }
 
-impl tt::Span for TokenId {}
-
 #[derive(Serialize, Deserialize, Debug)]
 pub struct FlatTree {
     subtree: Vec<u32>,
diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs
index 72f95643c8b..35d48a15543 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs
@@ -175,7 +175,7 @@ fn mk_child(
     env: &FxHashMap<String, String>,
     null_stderr: bool,
 ) -> io::Result<Child> {
-    let mut cmd = Command::new(path.as_os_str());
+    let mut cmd = Command::new(path);
     cmd.envs(env)
         .env("RUST_ANALYZER_INTERNALS_DO_NOT_USE", "this is unstable")
         .stdin(Stdio::piped())
@@ -183,7 +183,7 @@ fn mk_child(
         .stderr(if null_stderr { Stdio::null() } else { Stdio::inherit() });
     if cfg!(windows) {
         let mut path_var = std::ffi::OsString::new();
-        path_var.push(path.parent().unwrap().parent().unwrap().as_os_str());
+        path_var.push(path.parent().unwrap().parent().unwrap());
         path_var.push("\\bin;");
         path_var.push(std::env::var_os("PATH").unwrap_or_default());
         cmd.env("PATH", path_var);
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs
index 52b4cced5f5..22c34ff1678 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs
@@ -1,16 +1,11 @@
 //! Handles dynamic library loading for proc macro
 
-use std::{
-    fmt,
-    fs::File,
-    io,
-    path::{Path, PathBuf},
-};
+use std::{fmt, fs::File, io};
 
 use libloading::Library;
 use memmap2::Mmap;
 use object::Object;
-use paths::AbsPath;
+use paths::{AbsPath, Utf8Path, Utf8PathBuf};
 use proc_macro::bridge;
 use proc_macro_api::{read_dylib_info, ProcMacroKind};
 
@@ -26,7 +21,7 @@ fn is_derive_registrar_symbol(symbol: &str) -> bool {
     symbol.contains(NEW_REGISTRAR_SYMBOL)
 }
 
-fn find_registrar_symbol(file: &Path) -> io::Result<Option<String>> {
+fn find_registrar_symbol(file: &Utf8Path) -> io::Result<Option<String>> {
     let file = File::open(file)?;
     let buffer = unsafe { Mmap::map(&file)? };
 
@@ -62,12 +57,12 @@ fn find_registrar_symbol(file: &Path) -> io::Result<Option<String>> {
 ///
 /// It seems that on Windows that behaviour is default, so we do nothing in that case.
 #[cfg(windows)]
-fn load_library(file: &Path) -> Result<Library, libloading::Error> {
+fn load_library(file: &Utf8Path) -> Result<Library, libloading::Error> {
     unsafe { Library::new(file) }
 }
 
 #[cfg(unix)]
-fn load_library(file: &Path) -> Result<Library, libloading::Error> {
+fn load_library(file: &Utf8Path) -> Result<Library, libloading::Error> {
     use libloading::os::unix::Library as UnixLibrary;
     use std::os::raw::c_int;
 
@@ -116,14 +111,14 @@ struct ProcMacroLibraryLibloading {
 }
 
 impl ProcMacroLibraryLibloading {
-    fn open(file: &Path) -> Result<Self, LoadProcMacroDylibError> {
+    fn open(file: &Utf8Path) -> Result<Self, LoadProcMacroDylibError> {
         let symbol_name = find_registrar_symbol(file)?.ok_or_else(|| {
-            invalid_data_err(format!("Cannot find registrar symbol in file {}", file.display()))
+            invalid_data_err(format!("Cannot find registrar symbol in file {file}"))
         })?;
 
-        let abs_file: &AbsPath = file.try_into().map_err(|_| {
-            invalid_data_err(format!("expected an absolute path, got {}", file.display()))
-        })?;
+        let abs_file: &AbsPath = file
+            .try_into()
+            .map_err(|_| invalid_data_err(format!("expected an absolute path, got {file}")))?;
         let version_info = read_dylib_info(abs_file)?;
 
         let lib = load_library(file).map_err(invalid_data_err)?;
@@ -138,10 +133,10 @@ pub struct Expander {
 }
 
 impl Expander {
-    pub fn new(lib: &Path) -> Result<Expander, LoadProcMacroDylibError> {
+    pub fn new(lib: &Utf8Path) -> Result<Expander, LoadProcMacroDylibError> {
         // Some libraries for dynamic loading require canonicalized path even when it is
         // already absolute
-        let lib = lib.canonicalize()?;
+        let lib = lib.canonicalize_utf8()?;
 
         let lib = ensure_file_with_lock_free_access(&lib)?;
 
@@ -176,30 +171,26 @@ impl Expander {
 
 /// Copy the dylib to temp directory to prevent locking in Windows
 #[cfg(windows)]
-fn ensure_file_with_lock_free_access(path: &Path) -> io::Result<PathBuf> {
+fn ensure_file_with_lock_free_access(path: &Utf8Path) -> io::Result<Utf8PathBuf> {
     use std::collections::hash_map::RandomState;
-    use std::ffi::OsString;
     use std::hash::{BuildHasher, Hasher};
 
     if std::env::var("RA_DONT_COPY_PROC_MACRO_DLL").is_ok() {
         return Ok(path.to_path_buf());
     }
 
-    let mut to = std::env::temp_dir();
+    let mut to = Utf8PathBuf::from_path_buf(std::env::temp_dir()).unwrap();
 
     let file_name = path.file_name().ok_or_else(|| {
-        io::Error::new(
-            io::ErrorKind::InvalidInput,
-            format!("File path is invalid: {}", path.display()),
-        )
+        io::Error::new(io::ErrorKind::InvalidInput, format!("File path is invalid: {path}"))
     })?;
 
     // Generate a unique number by abusing `HashMap`'s hasher.
     // Maybe this will also "inspire" a libs team member to finally put `rand` in libstd.
     let t = RandomState::new().build_hasher().finish();
 
-    let mut unique_name = OsString::from(t.to_string());
-    unique_name.push(file_name);
+    let mut unique_name = t.to_string();
+    unique_name.push_str(file_name);
 
     to.push(unique_name);
     std::fs::copy(path, &to).unwrap();
@@ -207,6 +198,6 @@ fn ensure_file_with_lock_free_access(path: &Path) -> io::Result<PathBuf> {
 }
 
 #[cfg(unix)]
-fn ensure_file_with_lock_free_access(path: &Path) -> io::Result<PathBuf> {
-    Ok(path.to_path_buf())
+fn ensure_file_with_lock_free_access(path: &Utf8Path) -> io::Result<Utf8PathBuf> {
+    Ok(path.to_owned())
 }
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 831632c64c0..2472c1e3119 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
@@ -33,12 +33,11 @@ use std::{
     collections::{hash_map::Entry, HashMap},
     env,
     ffi::OsString,
-    fs,
-    path::{Path, PathBuf},
-    thread,
+    fs, thread,
     time::SystemTime,
 };
 
+use paths::{Utf8Path, Utf8PathBuf};
 use proc_macro_api::{
     msg::{
         self, deserialize_span_data_index_map, serialize_span_data_index_map, ExpnGlobals,
@@ -53,7 +52,7 @@ use crate::server::TokenStream;
 // see `build.rs`
 include!(concat!(env!("OUT_DIR"), "/rustc_version.rs"));
 
-trait ProcMacroSrvSpan: tt::Span {
+trait ProcMacroSrvSpan: Copy {
     type Server: proc_macro::bridge::server::Server<TokenStream = TokenStream<Self>>;
     fn make_server(call_site: Self, def_site: Self, mixed_site: Self) -> Self::Server;
 }
@@ -81,7 +80,7 @@ impl ProcMacroSrvSpan for Span {
 
 #[derive(Default)]
 pub struct ProcMacroSrv {
-    expanders: HashMap<(PathBuf, SystemTime), dylib::Expander>,
+    expanders: HashMap<(Utf8PathBuf, SystemTime), dylib::Expander>,
     span_mode: SpanMode,
 }
 
@@ -149,23 +148,22 @@ impl ProcMacroSrv {
 
     pub fn list_macros(
         &mut self,
-        dylib_path: &Path,
+        dylib_path: &Utf8Path,
     ) -> Result<Vec<(String, ProcMacroKind)>, String> {
         let expander = self.expander(dylib_path)?;
         Ok(expander.list_macros())
     }
 
-    fn expander(&mut self, path: &Path) -> Result<&dylib::Expander, String> {
+    fn expander(&mut self, path: &Utf8Path) -> Result<&dylib::Expander, String> {
         let time = fs::metadata(path)
             .and_then(|it| it.modified())
-            .map_err(|err| format!("Failed to get file metadata for {}: {err}", path.display()))?;
+            .map_err(|err| format!("Failed to get file metadata for {path}: {err}",))?;
 
         Ok(match self.expanders.entry((path.to_path_buf(), time)) {
-            Entry::Vacant(v) => {
-                v.insert(dylib::Expander::new(path).map_err(|err| {
-                    format!("Cannot create expander for {}: {err}", path.display())
-                })?)
-            }
+            Entry::Vacant(v) => v.insert(
+                dylib::Expander::new(path)
+                    .map_err(|err| format!("Cannot create expander for {path}: {err}",))?,
+            ),
             Entry::Occupied(e) => e.into_mut(),
         })
     }
@@ -306,6 +304,6 @@ impl Drop for EnvSnapshot {
 mod tests;
 
 #[cfg(test)]
-pub fn proc_macro_test_dylib_path() -> std::path::PathBuf {
+pub fn proc_macro_test_dylib_path() -> paths::Utf8PathBuf {
     proc_macro_test::PROC_MACRO_TEST_LOCATION.into()
 }
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/proc_macros.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/proc_macros.rs
index 686d5b0438a..631fd84aa24 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/proc_macros.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/proc_macros.rs
@@ -108,7 +108,7 @@ impl ProcMacros {
                     (trait_name.to_string(), ProcMacroKind::CustomDerive)
                 }
                 bridge::client::ProcMacro::Bang { name, .. } => {
-                    (name.to_string(), ProcMacroKind::FuncLike)
+                    (name.to_string(), ProcMacroKind::Bang)
                 }
                 bridge::client::ProcMacro::Attr { name, .. } => {
                     (name.to_string(), ProcMacroKind::Attr)
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/token_stream.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/token_stream.rs
index 408db60e872..b1a448427c6 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/token_stream.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/token_stream.rs
@@ -101,6 +101,8 @@ pub(super) struct TokenStreamBuilder<S> {
 /// pub(super)lic implementation details for the `TokenStream` type, such as iterators.
 pub(super) mod token_stream {
 
+    use core::fmt;
+
     use super::{TokenStream, TokenTree};
 
     /// An iterator over `TokenStream`'s `TokenTree`s.
@@ -122,7 +124,7 @@ pub(super) mod token_stream {
     ///
     /// NOTE: some errors may cause panics instead of returning `LexError`. We reserve the right to
     /// change these errors into `LexError`s later.
-    impl<S: tt::Span> TokenStream<S> {
+    impl<S: Copy + fmt::Debug> TokenStream<S> {
         pub(crate) fn from_str(src: &str, call_site: S) -> Result<TokenStream<S>, String> {
             let subtree =
                 mbe::parse_to_token_tree_static_span(call_site, src).ok_or("lexing error")?;
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs
index 11b008fc0b4..63342825380 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs
@@ -254,14 +254,14 @@ fn list_test_macros() {
     let res = list().join("\n");
 
     expect![[r#"
-        fn_like_noop [FuncLike]
-        fn_like_panic [FuncLike]
-        fn_like_error [FuncLike]
-        fn_like_clone_tokens [FuncLike]
-        fn_like_mk_literals [FuncLike]
-        fn_like_mk_idents [FuncLike]
-        fn_like_span_join [FuncLike]
-        fn_like_span_ops [FuncLike]
+        fn_like_noop [Bang]
+        fn_like_panic [Bang]
+        fn_like_error [Bang]
+        fn_like_clone_tokens [Bang]
+        fn_like_mk_literals [Bang]
+        fn_like_mk_idents [Bang]
+        fn_like_span_join [Bang]
+        fn_like_span_ops [Bang]
         attr_noop [Attr]
         attr_panic [Attr]
         attr_error [Attr]
diff --git a/src/tools/rust-analyzer/crates/project-model/Cargo.toml b/src/tools/rust-analyzer/crates/project-model/Cargo.toml
index 924a4a89e21..097ee1f75cd 100644
--- a/src/tools/rust-analyzer/crates/project-model/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/project-model/Cargo.toml
@@ -25,8 +25,9 @@ itertools.workspace = true
 
 # local deps
 base-db.workspace = true
+span.workspace = true
 cfg.workspace = true
-paths.workspace = true
+paths = { workspace = true, features = ["serde1"] }
 stdx.workspace = true
 toolchain.workspace = true
 
diff --git a/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs b/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs
index 709fc037174..d40eb26063d 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs
@@ -77,7 +77,7 @@ impl WorkspaceBuildScripts {
                 cmd.args(&config.extra_args);
 
                 cmd.arg("--manifest-path");
-                cmd.arg(workspace_root.join("Cargo.toml").as_os_str());
+                cmd.arg(workspace_root.join("Cargo.toml"));
 
                 if let Some(target_dir) = &config.target_dir {
                     cmd.arg("--target-dir").arg(target_dir);
@@ -354,16 +354,11 @@ impl WorkspaceBuildScripts {
                             }
                             // cargo_metadata crate returns default (empty) path for
                             // older cargos, which is not absolute, so work around that.
-                            let out_dir = mem::take(&mut message.out_dir).into_os_string();
-                            if !out_dir.is_empty() {
-                                let out_dir = AbsPathBuf::assert(PathBuf::from(out_dir));
+                            let out_dir = mem::take(&mut message.out_dir);
+                            if !out_dir.as_str().is_empty() {
+                                let out_dir = AbsPathBuf::assert(out_dir);
                                 // inject_cargo_env(package, package_build_data);
-                                // NOTE: cargo and rustc seem to hide non-UTF-8 strings from env! and option_env!()
-                                if let Some(out_dir) =
-                                    out_dir.as_os_str().to_str().map(|s| s.to_owned())
-                                {
-                                    data.envs.push(("OUT_DIR".to_owned(), out_dir));
-                                }
+                                data.envs.push(("OUT_DIR".to_owned(), out_dir.as_str().to_owned()));
                                 data.out_dir = Some(out_dir);
                                 data.cfgs = cfgs;
                             }
@@ -377,8 +372,8 @@ impl WorkspaceBuildScripts {
                                 if let Some(filename) =
                                     message.filenames.iter().find(|name| is_dylib(name))
                                 {
-                                    let filename = AbsPathBuf::assert(PathBuf::from(&filename));
-                                    data.proc_macro_dylib_path = Some(filename);
+                                    let filename = AbsPath::assert(filename);
+                                    data.proc_macro_dylib_path = Some(filename.to_owned());
                                 }
                             }
                         });
diff --git a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs
index 53b41ea1e87..51c1b094f7b 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs
@@ -1,17 +1,16 @@
 //! See [`CargoWorkspace`].
 
 use std::ops;
-use std::path::PathBuf;
 use std::str::from_utf8;
 
 use anyhow::Context;
-use base_db::Edition;
 use cargo_metadata::{CargoOpt, MetadataCommand};
 use la_arena::{Arena, Idx};
-use paths::{AbsPath, AbsPathBuf};
+use paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
 use rustc_hash::{FxHashMap, FxHashSet};
 use serde::Deserialize;
 use serde_json::from_value;
+use span::Edition;
 use toolchain::Tool;
 
 use crate::{utf8_stdout, InvocationLocation, ManifestPath, Sysroot};
@@ -100,7 +99,7 @@ pub struct CargoConfig {
     pub invocation_strategy: InvocationStrategy,
     pub invocation_location: InvocationLocation,
     /// Optional path to use instead of `target` when building
-    pub target_dir: Option<PathBuf>,
+    pub target_dir: Option<Utf8PathBuf>,
 }
 
 pub type Package = Idx<PackageData>;
@@ -262,7 +261,7 @@ impl CargoWorkspace {
                 }
             }
         }
-        meta.current_dir(current_dir.as_os_str());
+        meta.current_dir(current_dir);
 
         let mut other_options = vec![];
         // cargo metadata only supports a subset of flags of what cargo usually accepts, and usually
@@ -351,7 +350,7 @@ impl CargoWorkspace {
                 id: id.repr.clone(),
                 name,
                 version,
-                manifest: AbsPathBuf::assert(manifest_path.into()).try_into().unwrap(),
+                manifest: AbsPathBuf::assert(manifest_path).try_into().unwrap(),
                 targets: Vec::new(),
                 is_local,
                 is_member,
@@ -370,7 +369,7 @@ impl CargoWorkspace {
                 let tgt = targets.alloc(TargetData {
                     package: pkg,
                     name,
-                    root: AbsPathBuf::assert(src_path.into()),
+                    root: AbsPathBuf::assert(src_path),
                     kind: TargetKind::new(&kind),
                     required_features,
                 });
@@ -393,11 +392,9 @@ impl CargoWorkspace {
             packages[source].active_features.extend(node.features);
         }
 
-        let workspace_root =
-            AbsPathBuf::assert(PathBuf::from(meta.workspace_root.into_os_string()));
+        let workspace_root = AbsPathBuf::assert(meta.workspace_root);
 
-        let target_directory =
-            AbsPathBuf::assert(PathBuf::from(meta.target_directory.into_os_string()));
+        let target_directory = AbsPathBuf::assert(meta.target_directory);
 
         CargoWorkspace { packages, targets, workspace_root, target_directory }
     }
@@ -409,7 +406,7 @@ impl CargoWorkspace {
     pub fn target_by_root(&self, root: &AbsPath) -> Option<Target> {
         self.packages()
             .filter(|&pkg| self[pkg].is_member)
-            .find_map(|pkg| self[pkg].targets.iter().find(|&&it| &self[it].root == root))
+            .find_map(|pkg| self[pkg].targets.iter().find(|&&it| self[it].root == root))
             .copied()
     }
 
diff --git a/src/tools/rust-analyzer/crates/project-model/src/lib.rs b/src/tools/rust-analyzer/crates/project-model/src/lib.rs
index 5b91f5d8058..28696aa3277 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/lib.rs
@@ -127,8 +127,8 @@ impl ProjectManifest {
                 .filter_map(Result::ok)
                 .map(|it| it.path().join("Cargo.toml"))
                 .filter(|it| it.exists())
-                .map(AbsPathBuf::assert)
-                .filter_map(|it| it.try_into().ok())
+                .map(AbsPathBuf::try_from)
+                .filter_map(|it| it.ok()?.try_into().ok())
                 .collect()
         }
     }
diff --git a/src/tools/rust-analyzer/crates/project-model/src/project_json.rs b/src/tools/rust-analyzer/crates/project-model/src/project_json.rs
index fba0aaa8ce9..512588cc8f8 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/project_json.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/project_json.rs
@@ -49,12 +49,12 @@
 //! user explores them belongs to that extension (it's totally valid to change
 //! rust-project.json over time via configuration request!)
 
-use base_db::{CrateDisplayName, CrateId, CrateName, Dependency, Edition};
+use base_db::{CrateDisplayName, CrateId, CrateName, Dependency};
 use la_arena::RawIdx;
-use paths::{AbsPath, AbsPathBuf};
+use paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
 use rustc_hash::FxHashMap;
 use serde::{de, Deserialize};
-use std::path::PathBuf;
+use span::Edition;
 
 use crate::cfg_flag::CfgFlag;
 
@@ -113,7 +113,7 @@ impl ProjectJson {
                         .unwrap_or_else(|| root_module.starts_with(base));
                     let (include, exclude) = match crate_data.source {
                         Some(src) => {
-                            let absolutize = |dirs: Vec<PathBuf>| {
+                            let absolutize = |dirs: Vec<Utf8PathBuf>| {
                                 dirs.into_iter().map(absolutize_on_base).collect::<Vec<_>>()
                             };
                             (absolutize(src.include_dirs), absolutize(src.exclude_dirs))
@@ -176,15 +176,15 @@ impl ProjectJson {
 
 #[derive(Deserialize, Debug, Clone)]
 pub struct ProjectJsonData {
-    sysroot: Option<PathBuf>,
-    sysroot_src: Option<PathBuf>,
+    sysroot: Option<Utf8PathBuf>,
+    sysroot_src: Option<Utf8PathBuf>,
     crates: Vec<CrateData>,
 }
 
 #[derive(Deserialize, Debug, Clone)]
 struct CrateData {
     display_name: Option<String>,
-    root_module: PathBuf,
+    root_module: Utf8PathBuf,
     edition: EditionData,
     #[serde(default)]
     version: Option<semver::Version>,
@@ -194,7 +194,7 @@ struct CrateData {
     target: Option<String>,
     #[serde(default)]
     env: FxHashMap<String, String>,
-    proc_macro_dylib_path: Option<PathBuf>,
+    proc_macro_dylib_path: Option<Utf8PathBuf>,
     is_workspace_member: Option<bool>,
     source: Option<CrateSource>,
     #[serde(default)]
@@ -238,8 +238,8 @@ struct DepData {
 
 #[derive(Deserialize, Debug, Clone)]
 struct CrateSource {
-    include_dirs: Vec<PathBuf>,
-    exclude_dirs: Vec<PathBuf>,
+    include_dirs: Vec<Utf8PathBuf>,
+    exclude_dirs: Vec<Utf8PathBuf>,
 }
 
 fn deserialize_crate_name<'de, D>(de: D) -> std::result::Result<CrateName, D::Error>
diff --git a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
index 3127bae8b0c..1142d6243d2 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
@@ -4,13 +4,13 @@
 //! but we can't process `.rlib` and need source code instead. The source code
 //! is typically installed with `rustup component add rust-src` command.
 
-use std::{env, fs, iter, ops, path::PathBuf, process::Command, sync::Arc};
+use std::{env, fs, iter, ops, process::Command, sync::Arc};
 
 use anyhow::{format_err, Result};
 use base_db::CrateName;
 use itertools::Itertools;
 use la_arena::{Arena, Idx};
-use paths::{AbsPath, AbsPathBuf};
+use paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
 use rustc_hash::FxHashMap;
 use toolchain::{probe_for_binary, Tool};
 
@@ -419,7 +419,7 @@ fn discover_sysroot_dir(
     rustc.current_dir(current_dir).args(["--print", "sysroot"]);
     tracing::debug!("Discovering sysroot by {:?}", rustc);
     let stdout = utf8_stdout(rustc)?;
-    Ok(AbsPathBuf::assert(PathBuf::from(stdout)))
+    Ok(AbsPathBuf::assert(Utf8PathBuf::from(stdout)))
 }
 
 fn discover_sysroot_src_dir(sysroot_path: &AbsPathBuf) -> Option<AbsPathBuf> {
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 b9b1b701f6d..fc0b507b332 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs
@@ -1,12 +1,9 @@
-use std::{
-    ops::Deref,
-    path::{Path, PathBuf},
-};
+use std::ops::Deref;
 
 use base_db::{CrateGraph, FileId, ProcMacroPaths};
 use cfg::{CfgAtom, CfgDiff};
 use expect_test::{expect_file, ExpectFile};
-use paths::{AbsPath, AbsPathBuf};
+use paths::{AbsPath, AbsPathBuf, Utf8Path, Utf8PathBuf};
 use rustc_hash::FxHashMap;
 use serde::de::DeserializeOwned;
 use triomphe::Arc;
@@ -113,17 +110,16 @@ fn replace_root(s: &mut String, direction: bool) {
 fn replace_fake_sys_root(s: &mut String) {
     let fake_sysroot_path = get_test_path("fake-sysroot");
     let fake_sysroot_path = if cfg!(windows) {
-        let normalized_path =
-            fake_sysroot_path.to_str().expect("expected str").replace('\\', r#"\\"#);
+        let normalized_path = fake_sysroot_path.as_str().replace('\\', r#"\\"#);
         format!(r#"{}\\"#, normalized_path)
     } else {
-        format!("{}/", fake_sysroot_path.to_str().expect("expected str"))
+        format!("{}/", fake_sysroot_path.as_str())
     };
     *s = s.replace(&fake_sysroot_path, "$FAKESYSROOT$")
 }
 
-fn get_test_path(file: &str) -> PathBuf {
-    let base = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
+fn get_test_path(file: &str) -> Utf8PathBuf {
+    let base = Utf8PathBuf::from(env!("CARGO_MANIFEST_DIR"));
     base.join("test_data").join(file)
 }
 
@@ -139,7 +135,7 @@ fn get_fake_sysroot() -> Sysroot {
 fn rooted_project_json(data: ProjectJsonData) -> ProjectJson {
     let mut root = "$ROOT$".to_owned();
     replace_root(&mut root, true);
-    let path = Path::new(&root);
+    let path = Utf8Path::new(&root);
     let base = AbsPath::assert(path);
     ProjectJson::new(base, data)
 }
@@ -268,7 +264,7 @@ fn smoke_test_real_sysroot_cargo() {
 
     let cargo_workspace = CargoWorkspace::new(meta);
     let sysroot = Ok(Sysroot::discover(
-        AbsPath::assert(Path::new(env!("CARGO_MANIFEST_DIR"))),
+        AbsPath::assert(Utf8Path::new(env!("CARGO_MANIFEST_DIR"))),
         &Default::default(),
         true,
     )
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 1a138b17bad..b8c5885108d 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
@@ -6,13 +6,14 @@ use std::{collections::VecDeque, fmt, fs, iter, str::FromStr, sync};
 
 use anyhow::{format_err, Context};
 use base_db::{
-    CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Edition, Env,
-    FileId, LangCrateOrigin, ProcMacroPaths, TargetLayoutLoadResult,
+    CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Env, FileId,
+    LangCrateOrigin, ProcMacroPaths, TargetLayoutLoadResult,
 };
 use cfg::{CfgAtom, CfgDiff, CfgOptions};
 use paths::{AbsPath, AbsPathBuf};
 use rustc_hash::{FxHashMap, FxHashSet};
 use semver::Version;
+use span::Edition;
 use stdx::always;
 use toolchain::Tool;
 use triomphe::Arc;
@@ -718,19 +719,22 @@ impl ProjectWorkspace {
     ) -> (CrateGraph, ProcMacroPaths) {
         let _p = tracing::span!(tracing::Level::INFO, "ProjectWorkspace::to_crate_graph").entered();
 
-        let (mut crate_graph, proc_macros) = match self {
+        let ((mut crate_graph, proc_macros), sysroot) = match self {
             ProjectWorkspace::Json {
                 project,
                 sysroot,
                 rustc_cfg,
                 toolchain: _,
                 target_layout: _,
-            } => project_json_to_crate_graph(
-                rustc_cfg.clone(),
-                load,
-                project,
-                sysroot.as_ref().ok(),
-                extra_env,
+            } => (
+                project_json_to_crate_graph(
+                    rustc_cfg.clone(),
+                    load,
+                    project,
+                    sysroot.as_ref().ok(),
+                    extra_env,
+                ),
+                sysroot,
             ),
             ProjectWorkspace::Cargo {
                 cargo,
@@ -742,14 +746,17 @@ impl ProjectWorkspace {
                 toolchain: _,
                 target_layout: _,
                 cargo_config_extra_env: _,
-            } => cargo_to_crate_graph(
-                load,
-                rustc.as_ref().map(|a| a.as_ref()).ok(),
-                cargo,
-                sysroot.as_ref().ok(),
-                rustc_cfg.clone(),
-                cfg_overrides,
-                build_scripts,
+            } => (
+                cargo_to_crate_graph(
+                    load,
+                    rustc.as_ref().map(|a| a.as_ref()).ok(),
+                    cargo,
+                    sysroot.as_ref().ok(),
+                    rustc_cfg.clone(),
+                    cfg_overrides,
+                    build_scripts,
+                ),
+                sysroot,
             ),
             ProjectWorkspace::DetachedFiles {
                 files,
@@ -757,11 +764,20 @@ impl ProjectWorkspace {
                 rustc_cfg,
                 toolchain: _,
                 target_layout: _,
-            } => {
-                detached_files_to_crate_graph(rustc_cfg.clone(), load, files, sysroot.as_ref().ok())
-            }
+            } => (
+                detached_files_to_crate_graph(
+                    rustc_cfg.clone(),
+                    load,
+                    files,
+                    sysroot.as_ref().ok(),
+                ),
+                sysroot,
+            ),
         };
-        if crate_graph.patch_cfg_if() {
+
+        if matches!(sysroot.as_ref().map(|it| it.mode()), Ok(SysrootMode::Workspace(_)))
+            && crate_graph.patch_cfg_if()
+        {
             tracing::debug!("Patched std to depend on cfg-if")
         } else {
             tracing::debug!("Did not patch std to depend on cfg-if")
@@ -1077,6 +1093,8 @@ fn cargo_to_crate_graph(
         }
     }
 
+    let mut delayed_dev_deps = vec![];
+
     // Now add a dep edge from all targets of upstream to the lib
     // target of downstream.
     for pkg in cargo.packages() {
@@ -1091,11 +1109,31 @@ fn cargo_to_crate_graph(
                     continue;
                 }
 
+                // If the dependency is a dev-dependency with both crates being member libraries of
+                // the workspace we delay adding the edge. The reason can be read up on in
+                // https://github.com/rust-lang/rust-analyzer/issues/14167
+                // but in short, such an edge is able to cause some form of cycle in the crate graph
+                // for normal dependencies. If we do run into a cycle like this, we want to prefer
+                // the non dev-dependency edge, and so the easiest way to do that is by adding the
+                // dev-dependency edges last.
+                if dep.kind == DepKind::Dev
+                    && matches!(kind, TargetKind::Lib { .. })
+                    && cargo[dep.pkg].is_member
+                    && cargo[pkg].is_member
+                {
+                    delayed_dev_deps.push((from, name.clone(), to));
+                    continue;
+                }
+
                 add_dep(crate_graph, from, name.clone(), to)
             }
         }
     }
 
+    for (from, name, to) in delayed_dev_deps {
+        add_dep(crate_graph, from, name, to);
+    }
+
     if has_private {
         // If the user provided a path to rustc sources, we add all the rustc_private crates
         // and create dependencies on them for the crates which opt-in to that
@@ -1151,7 +1189,6 @@ fn detached_files_to_crate_graph(
         };
         let display_name = detached_file
             .file_stem()
-            .and_then(|os_str| os_str.to_str())
             .map(|file_stem| CrateDisplayName::from_canonical_name(file_stem.to_owned()));
         let detached_file_crate = crate_graph.add_crate_root(
             file_id,
@@ -1228,6 +1265,7 @@ fn handle_rustc_crates(
                 let kind @ TargetKind::Lib { is_proc_macro } = rustc_workspace[tgt].kind else {
                     continue;
                 };
+                let pkg_crates = &mut rustc_pkg_crates.entry(pkg).or_insert_with(Vec::new);
                 if let Some(file_id) = load(&rustc_workspace[tgt].root) {
                     let crate_id = add_target_crate_root(
                         crate_graph,
@@ -1246,7 +1284,7 @@ fn handle_rustc_crates(
                     if let Some(proc_macro) = libproc_macro {
                         add_proc_macro_dep(crate_graph, crate_id, proc_macro, is_proc_macro);
                     }
-                    rustc_pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id);
+                    pkg_crates.push(crate_id);
                 }
             }
         }
@@ -1533,7 +1571,7 @@ fn inject_cargo_env(package: &PackageData, env: &mut Env) {
     // CARGO_BIN_NAME, CARGO_BIN_EXE_<name>
 
     let manifest_dir = package.manifest.parent();
-    env.set("CARGO_MANIFEST_DIR", manifest_dir.as_os_str().to_string_lossy().into_owned());
+    env.set("CARGO_MANIFEST_DIR", manifest_dir.as_str().to_owned());
 
     // Not always right, but works for common cases.
     env.set("CARGO", "cargo".into());
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
index e6984d6f41b..6d70124188d 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
@@ -43,6 +43,7 @@ nohash-hasher.workspace = true
 always-assert = "0.2.0"
 walkdir = "2.3.2"
 semver.workspace = true
+memchr = "2.7.1"
 
 cfg.workspace = true
 flycheck.workspace = true
@@ -63,7 +64,7 @@ parser.workspace = true
 toolchain.workspace = true
 vfs-notify.workspace = true
 vfs.workspace = true
-memchr = "2.7.1"
+paths.workspace = true
 
 [target.'cfg(windows)'.dependencies]
 winapi = "0.3.9"
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 e747ec87b1c..78920f3abac 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
@@ -190,7 +190,7 @@ fn run_server() -> anyhow::Result<()> {
         Some(it) => it,
         None => {
             let cwd = env::current_dir()?;
-            AbsPathBuf::assert(cwd)
+            AbsPathBuf::assert_utf8(cwd)
         }
     };
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
index 5c474908e7a..fdd77199aa0 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -70,7 +70,7 @@ impl flags::AnalysisStats {
 
         let mut db_load_sw = self.stop_watch();
 
-        let path = AbsPathBuf::assert(env::current_dir()?.join(&self.path));
+        let path = AbsPathBuf::assert_utf8(env::current_dir()?.join(&self.path));
         let manifest = ProjectManifest::discover_single(&path)?;
 
         let mut workspace = ProjectWorkspace::load(manifest, &cargo_config, no_progress)?;
@@ -279,7 +279,8 @@ impl flags::AnalysisStats {
         let mut all = 0;
         let mut fail = 0;
         for &a in adts {
-            if db.generic_params(a.into()).iter().next().is_some() {
+            let generic_params = db.generic_params(a.into());
+            if generic_params.iter().next().is_some() || generic_params.iter_lt().next().is_some() {
                 // Data types with generics don't have layout.
                 continue;
             }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs
index bd2646126dc..79d6226debf 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/diagnostics.rs
@@ -16,7 +16,7 @@ impl flags::Diagnostics {
         let cargo_config =
             CargoConfig { sysroot: Some(RustLibSource::Discover), ..Default::default() };
         let with_proc_macro_server = if let Some(p) = &self.proc_macro_srv {
-            let path = vfs::AbsPathBuf::assert(std::env::current_dir()?.join(p));
+            let path = vfs::AbsPathBuf::assert_utf8(std::env::current_dir()?.join(p));
             ProcMacroServerChoice::Explicit(path)
         } else {
             ProcMacroServerChoice::Sysroot
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 3f68c5d053b..b3b8ab9a404 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
@@ -235,6 +235,7 @@ pub struct RunTests {
 #[derive(Debug)]
 pub struct RustcTests {
     pub rustc_repo: PathBuf,
+
     pub filter: Option<String>,
 }
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs
index f3f5ec1ebde..3ff9be7102f 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs
@@ -283,7 +283,7 @@ impl flags::Lsif {
             with_proc_macro_server: ProcMacroServerChoice::Sysroot,
             prefill_caches: false,
         };
-        let path = AbsPathBuf::assert(env::current_dir()?.join(self.path));
+        let path = AbsPathBuf::assert_utf8(env::current_dir()?.join(self.path));
         let manifest = ProjectManifest::discover_single(&path)?;
 
         let workspace = ProjectWorkspace::load(manifest, &cargo_config, no_progress)?;
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs
index 84f2e600874..eeec13a14be 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs
@@ -76,7 +76,7 @@ impl Tester {
         );
 
         let workspace = ProjectWorkspace::DetachedFiles {
-            files: vec![tmp_file.clone()],
+            files: vec![tmp_file],
             sysroot,
             rustc_cfg: vec![],
             toolchain: None,
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
index 1061a433a58..aef2c1be224 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs
@@ -27,7 +27,8 @@ impl flags::Scip {
             with_proc_macro_server: ProcMacroServerChoice::Sysroot,
             prefill_caches: true,
         };
-        let root = vfs::AbsPathBuf::assert(std::env::current_dir()?.join(&self.path)).normalize();
+        let root =
+            vfs::AbsPathBuf::assert_utf8(std::env::current_dir()?.join(&self.path)).normalize();
 
         let mut config = crate::config::Config::new(
             root.clone(),
@@ -63,12 +64,7 @@ impl flags::Scip {
                 special_fields: Default::default(),
             })
             .into(),
-            project_root: format!(
-                "file://{}",
-                root.as_os_str()
-                    .to_str()
-                    .ok_or(anyhow::format_err!("Unable to normalize project_root path"))?
-            ),
+            project_root: format!("file://{root}"),
             text_document_encoding: scip_types::TextEncoding::UTF8.into(),
             special_fields: Default::default(),
         };
@@ -216,7 +212,7 @@ fn get_relative_filepath(
     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_owned())
+    Some(vfs.file_path(file_id).as_path()?.strip_prefix(rootpath)?.as_str().to_owned())
 }
 
 // SCIP Ranges have a (very large) optimization that ranges if they are on the same line
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 cbf15246590..7475a8e6e6d 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -7,11 +7,7 @@
 //! configure the server itself, feature flags are passed into analysis, and
 //! tweak things like automatic insertion of `()` in completions.
 
-use std::{
-    fmt, iter,
-    ops::Not,
-    path::{Path, PathBuf},
-};
+use std::{fmt, iter, ops::Not};
 
 use cfg::{CfgAtom, CfgDiff};
 use flycheck::FlycheckConfig;
@@ -27,6 +23,7 @@ use ide_db::{
 };
 use itertools::Itertools;
 use lsp_types::{ClientCapabilities, MarkupKind};
+use paths::{Utf8Path, Utf8PathBuf};
 use project_model::{
     CargoConfig, CargoFeatures, ProjectJson, ProjectJsonData, ProjectManifest, RustLibSource,
 };
@@ -327,7 +324,7 @@ config_data! {
         /// These directories will be ignored by rust-analyzer. They are
         /// relative to the workspace root, and globs are not supported. You may
         /// also need to add the folders to Code's `files.watcherExclude`.
-        files_excludeDirs: Vec<PathBuf> = "[]",
+        files_excludeDirs: Vec<Utf8PathBuf> = "[]",
         /// Controls file watching implementation.
         files_watcher: FilesWatcherDef = "\"client\"",
 
@@ -378,6 +375,8 @@ config_data! {
         /// How to render the size information in a memory layout hover.
         hover_memoryLayout_size: Option<MemoryLayoutHoverRenderKindDef> = "\"both\"",
 
+        /// How many fields of a struct to display when hovering a struct.
+        hover_show_structFields: Option<usize> = "null",
         /// How many associated items of a trait to display when hovering a trait.
         hover_show_traitAssocItems: Option<usize> = "null",
 
@@ -516,7 +515,7 @@ config_data! {
         /// This config takes a map of crate names with the exported proc-macro names to ignore as values.
         procMacro_ignored: FxHashMap<Box<str>, Box<[Box<str>]>>          = "{}",
         /// Internal config, path to proc-macro server executable.
-        procMacro_server: Option<PathBuf>          = "null",
+        procMacro_server: Option<Utf8PathBuf>          = "null",
 
         /// Exclude imports from find-all-references.
         references_excludeImports: bool = "false",
@@ -864,7 +863,7 @@ impl Config {
         }
         let mut errors = Vec::new();
         self.detached_files =
-            get_field::<Vec<PathBuf>>(&mut json, &mut errors, "detachedFiles", None, "[]")
+            get_field::<Vec<Utf8PathBuf>>(&mut json, &mut errors, "detachedFiles", None, "[]")
                 .into_iter()
                 .map(AbsPathBuf::assert)
                 .collect();
@@ -956,7 +955,7 @@ impl Config {
     pub fn has_linked_projects(&self) -> bool {
         !self.data.linkedProjects.is_empty()
     }
-    pub fn linked_manifests(&self) -> impl Iterator<Item = &Path> + '_ {
+    pub fn linked_manifests(&self) -> impl Iterator<Item = &Utf8Path> + '_ {
         self.data.linkedProjects.iter().filter_map(|it| match it {
             ManifestOrProjectJson::Manifest(p) => Some(&**p),
             ManifestOrProjectJson::ProjectJson(_) => None,
@@ -1014,6 +1013,17 @@ impl Config {
         )
     }
 
+    pub fn did_change_watched_files_relative_pattern_support(&self) -> bool {
+        try_or_def!(
+            self.caps
+                .workspace
+                .as_ref()?
+                .did_change_watched_files
+                .as_ref()?
+                .relative_pattern_support?
+        )
+    }
+
     pub fn prefill_caches(&self) -> bool {
         self.data.cachePriming_enable
     }
@@ -1410,9 +1420,11 @@ impl Config {
         }
     }
 
-    fn target_dir_from_config(&self) -> Option<PathBuf> {
+    fn target_dir_from_config(&self) -> Option<Utf8PathBuf> {
         self.data.cargo_targetDir.as_ref().and_then(|target_dir| match target_dir {
-            TargetDirectory::UseSubdirectory(true) => Some(PathBuf::from("target/rust-analyzer")),
+            TargetDirectory::UseSubdirectory(true) => {
+                Some(Utf8PathBuf::from("target/rust-analyzer"))
+            }
             TargetDirectory::UseSubdirectory(false) => None,
             TargetDirectory::Directory(dir) if dir.is_relative() => Some(dir.clone()),
             TargetDirectory::Directory(_) => None,
@@ -1691,6 +1703,7 @@ impl Config {
             },
             keywords: self.data.hover_documentation_keywords_enable,
             max_trait_assoc_items_count: self.data.hover_show_traitAssocItems,
+            max_struct_field_count: self.data.hover_show_structFields,
         }
     }
 
@@ -1951,7 +1964,7 @@ where
 #[derive(Deserialize, Debug, Clone)]
 #[serde(untagged)]
 enum ManifestOrProjectJson {
-    Manifest(PathBuf),
+    Manifest(Utf8PathBuf),
     ProjectJson(ProjectJsonData),
 }
 
@@ -2134,7 +2147,7 @@ pub enum MemoryLayoutHoverRenderKindDef {
 #[serde(untagged)]
 pub enum TargetDirectory {
     UseSubdirectory(bool),
-    Directory(PathBuf),
+    Directory(Utf8PathBuf),
 }
 
 macro_rules! _config_data {
@@ -2263,7 +2276,7 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
             "type": "array",
             "items": { "type": "string" },
         },
-        "Vec<PathBuf>" => set! {
+        "Vec<Utf8PathBuf>" => set! {
             "type": "array",
             "items": { "type": "string" },
         },
@@ -2291,7 +2304,7 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
         "Option<String>" => set! {
             "type": ["null", "string"],
         },
-        "Option<PathBuf>" => set! {
+        "Option<Utf8PathBuf>" => set! {
             "type": ["null", "string"],
         },
         "Option<bool>" => set! {
@@ -2774,7 +2787,7 @@ mod tests {
             .unwrap();
         assert_eq!(config.data.cargo_targetDir, Some(TargetDirectory::UseSubdirectory(true)));
         assert!(
-            matches!(config.flycheck(), FlycheckConfig::CargoCommand { target_dir, .. } if target_dir == Some(PathBuf::from("target/rust-analyzer")))
+            matches!(config.flycheck(), FlycheckConfig::CargoCommand { target_dir, .. } if target_dir == Some(Utf8PathBuf::from("target/rust-analyzer")))
         );
     }
 
@@ -2793,10 +2806,10 @@ mod tests {
             .unwrap();
         assert_eq!(
             config.data.cargo_targetDir,
-            Some(TargetDirectory::Directory(PathBuf::from("other_folder")))
+            Some(TargetDirectory::Directory(Utf8PathBuf::from("other_folder")))
         );
         assert!(
-            matches!(config.flycheck(), FlycheckConfig::CargoCommand { target_dir, .. } if target_dir == Some(PathBuf::from("other_folder")))
+            matches!(config.flycheck(), FlycheckConfig::CargoCommand { target_dir, .. } if target_dir == Some(Utf8PathBuf::from("other_folder")))
         );
     }
 }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs
index 6e6cc53c251..7c4deac93f2 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs
@@ -519,14 +519,13 @@ fn clippy_code_description(code: Option<&str>) -> Option<lsp_types::CodeDescript
 #[cfg(test)]
 #[cfg(not(windows))]
 mod tests {
-    use std::path::Path;
-
     use crate::{config::Config, global_state::GlobalState};
 
     use super::*;
 
     use expect_test::{expect_file, ExpectFile};
     use lsp_types::ClientCapabilities;
+    use paths::Utf8Path;
 
     fn check(diagnostics_json: &str, expect: ExpectFile) {
         check_with_config(DiagnosticsMapConfig::default(), diagnostics_json, expect)
@@ -534,7 +533,7 @@ mod tests {
 
     fn check_with_config(config: DiagnosticsMapConfig, diagnostics_json: &str, expect: ExpectFile) {
         let diagnostic: flycheck::Diagnostic = serde_json::from_str(diagnostics_json).unwrap();
-        let workspace_root: &AbsPath = Path::new("/test/").try_into().unwrap();
+        let workspace_root: &AbsPath = Utf8Path::new("/test/").try_into().unwrap();
         let (sender, _) = crossbeam_channel::unbounded();
         let state = GlobalState::new(
             sender,
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 1b4c33d8586..8516ffa0dfa 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
@@ -307,16 +307,18 @@ impl GlobalState {
             for file in changed_files {
                 let vfs_path = vfs.file_path(file.file_id);
                 if let Some(path) = vfs_path.as_path() {
-                    let path = path.to_path_buf();
-                    if reload::should_refresh_for_change(&path, file.kind()) {
-                        workspace_structure_change = Some((path.clone(), false));
+                    has_structure_changes = file.is_created_or_deleted();
+
+                    if file.is_modified() && path.extension() == Some("rs") {
+                        modified_rust_files.push(file.file_id);
                     }
+
+                    let path = path.to_path_buf();
                     if file.is_created_or_deleted() {
-                        has_structure_changes = true;
-                        workspace_structure_change =
-                            Some((path, self.crate_graph_file_dependencies.contains(vfs_path)));
-                    } else if path.extension() == Some("rs".as_ref()) {
-                        modified_rust_files.push(file.file_id);
+                        workspace_structure_change.get_or_insert((path, false)).1 |=
+                            self.crate_graph_file_dependencies.contains(vfs_path);
+                    } else if reload::should_refresh_for_change(&path, file.kind()) {
+                        workspace_structure_change.get_or_insert((path.clone(), false));
                     }
                 }
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs
index ff213748b4f..b5c4a4f435e 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs
@@ -241,7 +241,7 @@ pub(crate) fn handle_did_change_watched_files(
     state: &mut GlobalState,
     params: DidChangeWatchedFilesParams,
 ) -> anyhow::Result<()> {
-    for change in params.changes {
+    for change in params.changes.iter().unique_by(|&it| &it.uri) {
         if let Ok(path) = from_proto::abs_path(&change.uri) {
             state.loader.handle.invalidate(path);
         }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
index 1d98457add3..77692ed3ae7 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
@@ -4,7 +4,6 @@
 use std::{
     fs,
     io::Write as _,
-    path::PathBuf,
     process::{self, Stdio},
 };
 
@@ -12,8 +11,8 @@ use anyhow::Context;
 
 use ide::{
     AnnotationConfig, AssistKind, AssistResolveStrategy, Cancellable, FilePosition, FileRange,
-    HoverAction, HoverGotoTypeData, InlayFieldsToResolve, Query, RangeInfo, RangeLimit,
-    ReferenceCategory, Runnable, RunnableKind, SingleResolve, SourceChange, TextEdit,
+    HoverAction, HoverGotoTypeData, InlayFieldsToResolve, Query, RangeInfo, ReferenceCategory,
+    Runnable, RunnableKind, SingleResolve, SourceChange, TextEdit,
 };
 use ide_db::SymbolKind;
 use itertools::Itertools;
@@ -27,6 +26,7 @@ use lsp_types::{
     SemanticTokensParams, SemanticTokensRangeParams, SemanticTokensRangeResult,
     SemanticTokensResult, SymbolInformation, SymbolTag, TextDocumentIdentifier, Url, WorkspaceEdit,
 };
+use paths::Utf8PathBuf;
 use project_model::{ManifestPath, ProjectWorkspace, TargetKind};
 use serde_json::json;
 use stdx::{format_to, never};
@@ -238,9 +238,12 @@ pub(crate) fn handle_discover_test(
     let (tests, scope) = match params.test_id {
         Some(id) => {
             let crate_id = id.split_once("::").map(|it| it.0).unwrap_or(&id);
-            (snap.analysis.discover_tests_in_crate_by_test_id(crate_id)?, vec![crate_id.to_owned()])
+            (
+                snap.analysis.discover_tests_in_crate_by_test_id(crate_id)?,
+                Some(vec![crate_id.to_owned()]),
+            )
         }
-        None => (snap.analysis.discover_test_roots()?, vec![]),
+        None => (snap.analysis.discover_test_roots()?, None),
     };
     for t in &tests {
         hack_recover_crate_name::insert_name(t.id.clone());
@@ -248,12 +251,13 @@ pub(crate) fn handle_discover_test(
     Ok(lsp_ext::DiscoverTestResults {
         tests: tests
             .into_iter()
-            .map(|t| {
+            .filter_map(|t| {
                 let line_index = t.file.and_then(|f| snap.file_line_index(f).ok());
                 to_proto::test_item(&snap, t, line_index.as_ref())
             })
             .collect(),
         scope,
+        scope_file: None,
     })
 }
 
@@ -1465,7 +1469,7 @@ pub(crate) fn handle_inlay_hints(
     let inlay_hints_config = snap.config.inlay_hints();
     Ok(Some(
         snap.analysis
-            .inlay_hints(&inlay_hints_config, file_id, Some(RangeLimit::Fixed(range)))?
+            .inlay_hints(&inlay_hints_config, file_id, Some(range))?
             .into_iter()
             .map(|it| {
                 to_proto::inlay_hint(
@@ -1499,10 +1503,11 @@ pub(crate) fn handle_inlay_hints_resolve(
     let hint_position = from_proto::offset(&line_index, original_hint.position)?;
     let mut forced_resolve_inlay_hints_config = snap.config.inlay_hints();
     forced_resolve_inlay_hints_config.fields_to_resolve = InlayFieldsToResolve::empty();
-    let resolve_hints = snap.analysis.inlay_hints(
+    let resolve_hints = snap.analysis.inlay_hints_resolve(
         &forced_resolve_inlay_hints_config,
         file_id,
-        Some(RangeLimit::NearestParent(hint_position)),
+        hint_position,
+        resolve_data.hash,
     )?;
 
     let mut resolved_hints = resolve_hints
@@ -1542,7 +1547,7 @@ pub(crate) fn handle_call_hierarchy_prepare(
     let RangeInfo { range: _, info: navs } = nav_info;
     let res = navs
         .into_iter()
-        .filter(|it| it.kind == Some(SymbolKind::Function))
+        .filter(|it| matches!(it.kind, Some(SymbolKind::Function | SymbolKind::Method)))
         .map(|it| to_proto::call_hierarchy_item(&snap, it))
         .collect::<Cancellable<Vec<_>>>()?;
 
@@ -1736,8 +1741,8 @@ pub(crate) fn handle_open_docs(
         _ => (None, None),
     };
 
-    let sysroot = sysroot.map(|p| p.root().as_os_str());
-    let target_dir = cargo.map(|cargo| cargo.target_directory()).map(|p| p.as_os_str());
+    let sysroot = sysroot.map(|p| p.root().as_str());
+    let target_dir = cargo.map(|cargo| cargo.target_directory()).map(|p| p.as_str());
 
     let Ok(remote_urls) = snap.analysis.external_docs(position, target_dir, sysroot) else {
         return if snap.config.local_docs() {
@@ -2042,7 +2047,7 @@ fn run_rustfmt(
             cmd
         }
         RustfmtConfig::CustomCommand { command, args } => {
-            let cmd = PathBuf::from(&command);
+            let cmd = Utf8PathBuf::from(&command);
             let workspace = CargoTargetSpec::for_file(snap, file_id)?;
             let mut cmd = match workspace {
                 Some(spec) => {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs
index 1c5a862c703..2731e845f35 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs
@@ -52,7 +52,7 @@ fn integrated_highlighting_benchmark() {
 
     let file_id = {
         let file = workspace_to_load.join(file);
-        let path = VfsPath::from(AbsPathBuf::assert(file));
+        let path = VfsPath::from(AbsPathBuf::assert_utf8(file));
         vfs.file_id(&path).unwrap_or_else(|| panic!("can't find virtual file for {path}"))
     };
 
@@ -112,7 +112,7 @@ fn integrated_completion_benchmark() {
 
     let file_id = {
         let file = workspace_to_load.join(file);
-        let path = VfsPath::from(AbsPathBuf::assert(file));
+        let path = VfsPath::from(AbsPathBuf::assert_utf8(file));
         vfs.file_id(&path).unwrap_or_else(|| panic!("can't find virtual file for {path}"))
     };
 
@@ -274,7 +274,7 @@ fn integrated_diagnostics_benchmark() {
 
     let file_id = {
         let file = workspace_to_load.join(file);
-        let path = VfsPath::from(AbsPathBuf::assert(file));
+        let path = VfsPath::from(AbsPathBuf::assert_utf8(file));
         vfs.file_id(&path).unwrap_or_else(|| panic!("can't find virtual file for {path}"))
     };
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
index 710ce7f8acb..eac982f1b27 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
@@ -194,7 +194,8 @@ pub struct TestItem {
 #[serde(rename_all = "camelCase")]
 pub struct DiscoverTestResults {
     pub tests: Vec<TestItem>,
-    pub scope: Vec<String>,
+    pub scope: Option<Vec<String>>,
+    pub scope_file: Option<Vec<TextDocumentIdentifier>>,
 }
 
 pub enum DiscoverTest {}
@@ -800,6 +801,7 @@ pub struct CompletionResolveData {
 #[derive(Debug, Serialize, Deserialize)]
 pub struct InlayHintResolveData {
     pub file_id: u32,
+    pub hash: u64,
 }
 
 #[derive(Debug, Serialize, Deserialize)]
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/semantic_tokens.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/semantic_tokens.rs
index c5081c4bea0..3e00222b752 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/semantic_tokens.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/semantic_tokens.rs
@@ -127,13 +127,14 @@ macro_rules! define_semantic_token_modifiers {
 
 define_semantic_token_modifiers![
     standard {
+        ASYNC,
         DOCUMENTATION,
         DECLARATION,
         STATIC,
         DEFAULT_LIBRARY,
     }
     custom {
-        (ASYNC, "async"),
+        (ASSOCIATED, "associated"),
         (ATTRIBUTE_MODIFIER, "attribute"),
         (CALLABLE, "callable"),
         (CONSTANT, "constant"),
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
index e77d0c13bf2..d8bb12528b9 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
@@ -1,7 +1,7 @@
 //! Conversion of rust-analyzer specific types to lsp_types equivalents.
 use std::{
     iter::once,
-    mem, path,
+    mem,
     sync::atomic::{AtomicU32, Ordering},
 };
 
@@ -13,8 +13,9 @@ use ide::{
     NavigationTarget, ReferenceCategory, RenameError, Runnable, Severity, SignatureHelp,
     SnippetEdit, SourceChange, StructureNodeKind, SymbolKind, TextEdit, TextRange, TextSize,
 };
-use ide_db::rust_doc::format_docs;
+use ide_db::{rust_doc::format_docs, FxHasher};
 use itertools::Itertools;
+use paths::{Utf8Component, Utf8Prefix};
 use semver::VersionReq;
 use serde_json::to_value;
 use vfs::AbsPath;
@@ -52,6 +53,7 @@ pub(crate) fn range(line_index: &LineIndex, range: TextRange) -> lsp_types::Rang
 pub(crate) fn symbol_kind(symbol_kind: SymbolKind) -> lsp_types::SymbolKind {
     match symbol_kind {
         SymbolKind::Function => lsp_types::SymbolKind::FUNCTION,
+        SymbolKind::Method => lsp_types::SymbolKind::METHOD,
         SymbolKind::Struct => lsp_types::SymbolKind::STRUCT,
         SymbolKind::Enum => lsp_types::SymbolKind::ENUM,
         SymbolKind::Variant => lsp_types::SymbolKind::ENUM_MEMBER,
@@ -122,12 +124,12 @@ pub(crate) fn completion_item_kind(
         CompletionItemKind::BuiltinType => lsp_types::CompletionItemKind::STRUCT,
         CompletionItemKind::InferredType => lsp_types::CompletionItemKind::SNIPPET,
         CompletionItemKind::Keyword => lsp_types::CompletionItemKind::KEYWORD,
-        CompletionItemKind::Method => lsp_types::CompletionItemKind::METHOD,
         CompletionItemKind::Snippet => lsp_types::CompletionItemKind::SNIPPET,
         CompletionItemKind::UnresolvedReference => lsp_types::CompletionItemKind::REFERENCE,
         CompletionItemKind::Expression => lsp_types::CompletionItemKind::SNIPPET,
         CompletionItemKind::SymbolKind(symbol) => match symbol {
             SymbolKind::Attribute => lsp_types::CompletionItemKind::FUNCTION,
+            SymbolKind::Method => lsp_types::CompletionItemKind::METHOD,
             SymbolKind::Const => lsp_types::CompletionItemKind::CONSTANT,
             SymbolKind::ConstParam => lsp_types::CompletionItemKind::TYPE_PARAMETER,
             SymbolKind::Derive => lsp_types::CompletionItemKind::FUNCTION,
@@ -444,30 +446,42 @@ pub(crate) fn inlay_hint(
     fields_to_resolve: &InlayFieldsToResolve,
     line_index: &LineIndex,
     file_id: FileId,
-    inlay_hint: InlayHint,
+    mut inlay_hint: InlayHint,
 ) -> Cancellable<lsp_types::InlayHint> {
-    let needs_resolve = inlay_hint.needs_resolve;
-    let (label, tooltip, mut something_to_resolve) =
-        inlay_hint_label(snap, fields_to_resolve, needs_resolve, inlay_hint.label)?;
+    let resolve_hash = inlay_hint.needs_resolve().then(|| {
+        std::hash::BuildHasher::hash_one(
+            &std::hash::BuildHasherDefault::<FxHasher>::default(),
+            &inlay_hint,
+        )
+    });
 
+    let mut something_to_resolve = false;
     let text_edits = if snap
         .config
         .visual_studio_code_version()
         // https://github.com/microsoft/vscode/issues/193124
         .map_or(true, |version| VersionReq::parse(">=1.86.0").unwrap().matches(version))
-        && needs_resolve
+        && resolve_hash.is_some()
         && fields_to_resolve.resolve_text_edits
     {
         something_to_resolve |= inlay_hint.text_edit.is_some();
         None
     } else {
-        inlay_hint.text_edit.map(|it| text_edit_vec(line_index, it))
+        inlay_hint.text_edit.take().map(|it| text_edit_vec(line_index, it))
     };
-
-    let data = if needs_resolve && something_to_resolve {
-        Some(to_value(lsp_ext::InlayHintResolveData { file_id: file_id.index() }).unwrap())
-    } else {
-        None
+    let (label, tooltip) = inlay_hint_label(
+        snap,
+        fields_to_resolve,
+        &mut something_to_resolve,
+        resolve_hash.is_some(),
+        inlay_hint.label,
+    )?;
+
+    let data = match resolve_hash {
+        Some(hash) if something_to_resolve => Some(
+            to_value(lsp_ext::InlayHintResolveData { file_id: file_id.index(), hash }).unwrap(),
+        ),
+        _ => None,
     };
 
     Ok(lsp_types::InlayHint {
@@ -492,15 +506,15 @@ pub(crate) fn inlay_hint(
 fn inlay_hint_label(
     snap: &GlobalStateSnapshot,
     fields_to_resolve: &InlayFieldsToResolve,
+    something_to_resolve: &mut bool,
     needs_resolve: bool,
     mut label: InlayHintLabel,
-) -> Cancellable<(lsp_types::InlayHintLabel, Option<lsp_types::InlayHintTooltip>, bool)> {
-    let mut something_to_resolve = false;
+) -> Cancellable<(lsp_types::InlayHintLabel, Option<lsp_types::InlayHintTooltip>)> {
     let (label, tooltip) = match &*label.parts {
         [InlayHintLabelPart { linked_location: None, .. }] => {
             let InlayHintLabelPart { text, tooltip, .. } = label.parts.pop().unwrap();
             let hint_tooltip = if needs_resolve && fields_to_resolve.resolve_hint_tooltip {
-                something_to_resolve |= tooltip.is_some();
+                *something_to_resolve |= tooltip.is_some();
                 None
             } else {
                 match tooltip {
@@ -524,7 +538,7 @@ fn inlay_hint_label(
                 .into_iter()
                 .map(|part| {
                     let tooltip = if needs_resolve && fields_to_resolve.resolve_label_tooltip {
-                        something_to_resolve |= part.tooltip.is_some();
+                        *something_to_resolve |= part.tooltip.is_some();
                         None
                     } else {
                         match part.tooltip {
@@ -543,7 +557,7 @@ fn inlay_hint_label(
                         }
                     };
                     let location = if needs_resolve && fields_to_resolve.resolve_label_location {
-                        something_to_resolve |= part.linked_location.is_some();
+                        *something_to_resolve |= part.linked_location.is_some();
                         None
                     } else {
                         part.linked_location.map(|range| location(snap, range)).transpose()?
@@ -559,7 +573,7 @@ fn inlay_hint_label(
             (lsp_types::InlayHintLabel::LabelParts(parts), None)
         }
     };
-    Ok((label, tooltip, something_to_resolve))
+    Ok((label, tooltip))
 }
 
 static TOKEN_RESULT_COUNTER: AtomicU32 = AtomicU32::new(1);
@@ -636,8 +650,7 @@ pub(crate) fn semantic_token_delta(
 fn semantic_token_type_and_modifiers(
     highlight: Highlight,
 ) -> (lsp_types::SemanticTokenType, semantic_tokens::ModifierSet) {
-    let mut mods = semantic_tokens::ModifierSet::default();
-    let type_ = match highlight.tag {
+    let ty = match highlight.tag {
         HlTag::Symbol(symbol) => match symbol {
             SymbolKind::Attribute => semantic_tokens::DECORATOR,
             SymbolKind::Derive => semantic_tokens::DERIVE,
@@ -653,22 +666,10 @@ fn semantic_token_type_and_modifiers(
             SymbolKind::SelfParam => semantic_tokens::SELF_KEYWORD,
             SymbolKind::SelfType => semantic_tokens::SELF_TYPE_KEYWORD,
             SymbolKind::Local => semantic_tokens::VARIABLE,
-            SymbolKind::Function => {
-                if highlight.mods.contains(HlMod::Associated) {
-                    semantic_tokens::METHOD
-                } else {
-                    semantic_tokens::FUNCTION
-                }
-            }
-            SymbolKind::Const => {
-                mods |= semantic_tokens::CONSTANT;
-                mods |= semantic_tokens::STATIC;
-                semantic_tokens::VARIABLE
-            }
-            SymbolKind::Static => {
-                mods |= semantic_tokens::STATIC;
-                semantic_tokens::VARIABLE
-            }
+            SymbolKind::Method => semantic_tokens::METHOD,
+            SymbolKind::Function => semantic_tokens::FUNCTION,
+            SymbolKind::Const => semantic_tokens::VARIABLE,
+            SymbolKind::Static => semantic_tokens::VARIABLE,
             SymbolKind::Struct => semantic_tokens::STRUCT,
             SymbolKind::Enum => semantic_tokens::ENUM,
             SymbolKind::Variant => semantic_tokens::ENUM_MEMBER,
@@ -715,12 +716,14 @@ fn semantic_token_type_and_modifiers(
         },
     };
 
+    let mut mods = semantic_tokens::ModifierSet::default();
     for modifier in highlight.mods.iter() {
         let modifier = match modifier {
-            HlMod::Associated => continue,
+            HlMod::Associated => semantic_tokens::ASSOCIATED,
             HlMod::Async => semantic_tokens::ASYNC,
             HlMod::Attribute => semantic_tokens::ATTRIBUTE_MODIFIER,
             HlMod::Callable => semantic_tokens::CALLABLE,
+            HlMod::Const => semantic_tokens::CONSTANT,
             HlMod::Consuming => semantic_tokens::CONSUMING,
             HlMod::ControlFlow => semantic_tokens::CONTROL_FLOW,
             HlMod::CrateRoot => semantic_tokens::CRATE_ROOT,
@@ -742,7 +745,7 @@ fn semantic_token_type_and_modifiers(
         mods |= modifier;
     }
 
-    (type_, mods)
+    (ty, mods)
 }
 
 pub(crate) fn folding_range(
@@ -814,9 +817,9 @@ pub(crate) fn url(snap: &GlobalStateSnapshot, file_id: FileId) -> lsp_types::Url
 /// When processing non-windows path, this is essentially the same as `Url::from_file_path`.
 pub(crate) fn url_from_abs_path(path: &AbsPath) -> lsp_types::Url {
     let url = lsp_types::Url::from_file_path(path).unwrap();
-    match path.as_ref().components().next() {
-        Some(path::Component::Prefix(prefix))
-            if matches!(prefix.kind(), path::Prefix::Disk(_) | path::Prefix::VerbatimDisk(_)) =>
+    match path.components().next() {
+        Some(Utf8Component::Prefix(prefix))
+            if matches!(prefix.kind(), Utf8Prefix::Disk(_) | Utf8Prefix::VerbatimDisk(_)) =>
         {
             // Need to lowercase driver letter
         }
@@ -1514,8 +1517,8 @@ pub(crate) fn test_item(
     snap: &GlobalStateSnapshot,
     test_item: ide::TestItem,
     line_index: Option<&LineIndex>,
-) -> lsp_ext::TestItem {
-    lsp_ext::TestItem {
+) -> Option<lsp_ext::TestItem> {
+    Some(lsp_ext::TestItem {
         id: test_item.id,
         label: test_item.label,
         kind: match test_item.kind {
@@ -1530,9 +1533,9 @@ pub(crate) fn test_item(
                     | project_model::TargetKind::Example
                     | project_model::TargetKind::BuildScript
                     | project_model::TargetKind::Other => lsp_ext::TestItemKind::Package,
-                    project_model::TargetKind::Test | project_model::TargetKind::Bench => {
-                        lsp_ext::TestItemKind::Test
-                    }
+                    project_model::TargetKind::Test => lsp_ext::TestItemKind::Test,
+                    // benches are not tests needed to be shown in the test explorer
+                    project_model::TargetKind::Bench => return None,
                 }
             }
             ide::TestItemKind::Module => lsp_ext::TestItemKind::Module,
@@ -1548,7 +1551,7 @@ pub(crate) fn test_item(
             .map(|f| lsp_types::TextDocumentIdentifier { uri: url(snap, f) }),
         range: line_index.and_then(|l| Some(range(l, test_item.text_range?))),
         runnable: test_item.runnable.and_then(|r| runnable(snap, r).ok()),
-    }
+    })
 }
 
 pub(crate) mod command {
@@ -2728,12 +2731,12 @@ struct ProcMacro {
     #[test]
     #[cfg(target_os = "windows")]
     fn test_lowercase_drive_letter() {
-        use std::path::Path;
+        use paths::Utf8Path;
 
-        let url = url_from_abs_path(Path::new("C:\\Test").try_into().unwrap());
+        let url = url_from_abs_path(Utf8Path::new("C:\\Test").try_into().unwrap());
         assert_eq!(url.to_string(), "file:///c:/Test");
 
-        let url = url_from_abs_path(Path::new(r#"\\localhost\C$\my_dir"#).try_into().unwrap());
+        let url = url_from_abs_path(Utf8Path::new(r#"\\localhost\C$\my_dir"#).try_into().unwrap());
         assert_eq!(url.to_string(), "file://localhost/C$/my_dir");
     }
 }
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 ffe56e41435..38df3235125 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
@@ -9,9 +9,8 @@ use std::{
 use always_assert::always;
 use crossbeam_channel::{never, select, Receiver};
 use ide_db::base_db::{SourceDatabase, SourceDatabaseExt, VfsPath};
-use itertools::Itertools;
 use lsp_server::{Connection, Notification, Request};
-use lsp_types::notification::Notification as _;
+use lsp_types::{notification::Notification as _, TextDocumentIdentifier};
 use stdx::thread::ThreadIntent;
 use vfs::FileId;
 
@@ -533,31 +532,29 @@ impl GlobalState {
             let snapshot = self.snapshot();
             move || {
                 let tests = subscriptions
-                    .into_iter()
-                    .filter_map(|f| snapshot.analysis.crates_for(f).ok())
-                    .flatten()
-                    .unique()
-                    .filter_map(|c| snapshot.analysis.discover_tests_in_crate(c).ok())
+                    .iter()
+                    .copied()
+                    .filter_map(|f| snapshot.analysis.discover_tests_in_file(f).ok())
                     .flatten()
                     .collect::<Vec<_>>();
                 for t in &tests {
                     hack_recover_crate_name::insert_name(t.id.clone());
                 }
-                let scope = tests
-                    .iter()
-                    .filter_map(|t| Some(t.id.split_once("::")?.0))
-                    .unique()
-                    .map(|it| it.to_owned())
-                    .collect();
                 Task::DiscoverTest(lsp_ext::DiscoverTestResults {
                     tests: tests
                         .into_iter()
-                        .map(|t| {
+                        .filter_map(|t| {
                             let line_index = t.file.and_then(|f| snapshot.file_line_index(f).ok());
                             to_proto::test_item(&snapshot, t, line_index.as_ref())
                         })
                         .collect(),
-                    scope,
+                    scope: None,
+                    scope_file: Some(
+                        subscriptions
+                            .into_iter()
+                            .map(|f| TextDocumentIdentifier { uri: to_proto::url(&snapshot, f) })
+                            .collect(),
+                    ),
                 })
             }
         });
@@ -653,7 +650,7 @@ impl GlobalState {
                 };
 
                 if let Some(state) = state {
-                    self.report_progress("Building", state, msg, None, None);
+                    self.report_progress("Building build-artifacts", state, msg, None, None);
                 }
             }
             Task::LoadProcMacros(progress) => {
@@ -669,7 +666,7 @@ impl GlobalState {
                 };
 
                 if let Some(state) = state {
-                    self.report_progress("Loading", state, msg, None, None);
+                    self.report_progress("Loading proc-macros", state, msg, None, None);
                 }
             }
             Task::BuildDepsHaveChanged => self.build_deps_changed = true,
@@ -714,10 +711,9 @@ impl GlobalState {
                     message += &format!(
                         ": {}",
                         match dir.strip_prefix(self.config.root_path()) {
-                            Some(relative_path) => relative_path.as_ref(),
+                            Some(relative_path) => relative_path.as_utf8_path(),
                             None => dir.as_ref(),
                         }
-                        .display()
                     );
                 }
 
@@ -861,7 +857,7 @@ impl GlobalState {
                 let title = if self.flycheck.len() == 1 {
                     format!("{}", self.config.flycheck())
                 } else {
-                    format!("cargo check (#{})", id + 1)
+                    format!("{} (#{})", self.config.flycheck(), id + 1)
                 };
                 self.report_progress(
                     &title,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
index c2725e1fad9..771a5599f6f 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
@@ -26,7 +26,6 @@ use itertools::Itertools;
 use load_cargo::{load_proc_macro, ProjectFolders};
 use proc_macro_api::ProcMacroServer;
 use project_model::{ProjectWorkspace, WorkspaceBuildScripts};
-use rustc_hash::FxHashSet;
 use stdx::{format_to, thread::ThreadIntent};
 use triomphe::Arc;
 use vfs::{AbsPath, AbsPathBuf, ChangeKind};
@@ -185,10 +184,8 @@ impl GlobalState {
                 message.push_str(
                     "`rust-analyzer.linkedProjects` have been specified, which may be incorrect. Specified project paths:\n",
                 );
-                message.push_str(&format!(
-                    "    {}",
-                    self.config.linked_manifests().map(|it| it.display()).format("\n    ")
-                ));
+                message
+                    .push_str(&format!("    {}", self.config.linked_manifests().format("\n    ")));
                 if self.config.has_linked_project_jsons() {
                     message.push_str("\nAdditionally, one or more project jsons are specified")
                 }
@@ -431,27 +428,46 @@ impl GlobalState {
         }
 
         if let FilesWatcher::Client = self.config.files().watcher {
-            let registration_options = lsp_types::DidChangeWatchedFilesRegistrationOptions {
-                watchers: self
-                    .workspaces
-                    .iter()
-                    .flat_map(|ws| ws.to_roots())
-                    .filter(|it| it.is_local)
+            let filter =
+                self.workspaces.iter().flat_map(|ws| ws.to_roots()).filter(|it| it.is_local);
+
+            let watchers = if self.config.did_change_watched_files_relative_pattern_support() {
+                // When relative patterns are supported by the client, prefer using them
+                filter
+                    .flat_map(|root| {
+                        root.include.into_iter().flat_map(|base| {
+                            [(base.clone(), "**/*.rs"), (base, "**/Cargo.{lock,toml}")]
+                        })
+                    })
+                    .map(|(base, pat)| lsp_types::FileSystemWatcher {
+                        glob_pattern: lsp_types::GlobPattern::Relative(
+                            lsp_types::RelativePattern {
+                                base_uri: lsp_types::OneOf::Right(
+                                    lsp_types::Url::from_file_path(base).unwrap(),
+                                ),
+                                pattern: pat.to_owned(),
+                            },
+                        ),
+                        kind: None,
+                    })
+                    .collect()
+            } else {
+                // When they're not, integrate the base to make them into absolute patterns
+                filter
                     .flat_map(|root| {
-                        root.include.into_iter().flat_map(|it| {
-                            [
-                                format!("{it}/**/*.rs"),
-                                format!("{it}/**/Cargo.toml"),
-                                format!("{it}/**/Cargo.lock"),
-                            ]
+                        root.include.into_iter().flat_map(|base| {
+                            [format!("{base}/**/*.rs"), format!("{base}/**/Cargo.{{lock,toml}}")]
                         })
                     })
                     .map(|glob_pattern| lsp_types::FileSystemWatcher {
                         glob_pattern: lsp_types::GlobPattern::String(glob_pattern),
                         kind: None,
                     })
-                    .collect(),
+                    .collect()
             };
+
+            let registration_options =
+                lsp_types::DidChangeWatchedFilesRegistrationOptions { watchers };
             let registration = lsp_types::Registration {
                 id: "workspace/didChangeWatchedFiles".to_owned(),
                 method: "workspace/didChangeWatchedFiles".to_owned(),
@@ -525,26 +541,23 @@ impl GlobalState {
     fn recreate_crate_graph(&mut self, cause: String) {
         // crate graph construction relies on these paths, record them so when one of them gets
         // deleted or created we trigger a reconstruction of the crate graph
-        let mut crate_graph_file_dependencies = FxHashSet::default();
+        let mut crate_graph_file_dependencies = mem::take(&mut self.crate_graph_file_dependencies);
+        self.report_progress(
+            "Building CrateGraph",
+            crate::lsp::utils::Progress::Begin,
+            None,
+            None,
+            None,
+        );
 
         let (crate_graph, proc_macro_paths, layouts, toolchains) = {
             // Create crate graph from all the workspaces
             let vfs = &mut self.vfs.write().0;
-            let loader = &mut self.loader;
 
             let load = |path: &AbsPath| {
-                let _p = tracing::span!(tracing::Level::DEBUG, "switch_workspaces::load").entered();
                 let vfs_path = vfs::VfsPath::from(path.to_path_buf());
                 crate_graph_file_dependencies.insert(vfs_path.clone());
-                match vfs.file_id(&vfs_path) {
-                    Some(file_id) => Some(file_id),
-                    None => {
-                        // FIXME: Consider not loading this here?
-                        let contents = loader.handle.load_sync(path);
-                        vfs.set_file_contents(vfs_path.clone(), contents);
-                        vfs.file_id(&vfs_path)
-                    }
-                }
+                vfs.file_id(&vfs_path)
             };
 
             ws_to_crate_graph(&self.workspaces, self.config.extra_env(), load)
@@ -564,6 +577,13 @@ impl GlobalState {
         change.set_toolchains(toolchains);
         self.analysis_host.apply_change(change);
         self.crate_graph_file_dependencies = crate_graph_file_dependencies;
+        self.report_progress(
+            "Building CrateGraph",
+            crate::lsp::utils::Progress::End,
+            None,
+            None,
+            None,
+        );
 
         self.process_changes();
         self.reload_flycheck();
@@ -732,6 +752,8 @@ pub fn ws_to_crate_graph(
         });
         proc_macro_paths.push(crate_proc_macros);
     }
+    crate_graph.shrink_to_fit();
+    proc_macro_paths.shrink_to_fit();
     (crate_graph, proc_macro_paths, layouts, toolchains)
 }
 
@@ -739,7 +761,7 @@ pub(crate) fn should_refresh_for_change(path: &AbsPath, change_kind: ChangeKind)
     const IMPLICIT_TARGET_FILES: &[&str] = &["build.rs", "src/main.rs", "src/lib.rs"];
     const IMPLICIT_TARGET_DIRS: &[&str] = &["src/bin", "examples", "tests", "benches"];
 
-    let file_name = match path.file_name().unwrap_or_default().to_str() {
+    let file_name = match path.file_name() {
         Some(it) => it,
         None => return false,
     };
@@ -754,18 +776,18 @@ pub(crate) fn should_refresh_for_change(path: &AbsPath, change_kind: ChangeKind)
     // .cargo/config{.toml}
     if path.extension().unwrap_or_default() != "rs" {
         let is_cargo_config = matches!(file_name, "config.toml" | "config")
-            && path.parent().map(|parent| parent.as_ref().ends_with(".cargo")).unwrap_or(false);
+            && path.parent().map(|parent| parent.as_str().ends_with(".cargo")).unwrap_or(false);
         return is_cargo_config;
     }
 
-    if IMPLICIT_TARGET_FILES.iter().any(|it| path.as_ref().ends_with(it)) {
+    if IMPLICIT_TARGET_FILES.iter().any(|it| path.as_str().ends_with(it)) {
         return true;
     }
     let parent = match path.parent() {
         Some(it) => it,
         None => return false,
     };
-    if IMPLICIT_TARGET_DIRS.iter().any(|it| parent.as_ref().ends_with(it)) {
+    if IMPLICIT_TARGET_DIRS.iter().any(|it| parent.as_str().ends_with(it)) {
         return true;
     }
     if file_name == "main.rs" {
@@ -773,7 +795,7 @@ pub(crate) fn should_refresh_for_change(path: &AbsPath, change_kind: ChangeKind)
             Some(it) => it,
             None => return false,
         };
-        if IMPLICIT_TARGET_DIRS.iter().any(|it| grand_parent.as_ref().ends_with(it)) {
+        if IMPLICIT_TARGET_DIRS.iter().any(|it| grand_parent.as_str().ends_with(it)) {
             return true;
         }
     }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/crate_graph.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/crate_graph.rs
index efd42fadf7e..cf38032b941 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/crate_graph.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/crate_graph.rs
@@ -60,7 +60,7 @@ fn get_fake_sysroot() -> Sysroot {
     let sysroot_path = get_fake_sysroot_path();
     // there's no `libexec/` directory with a `proc-macro-srv` binary in that
     // fake sysroot, so we give them both the same path:
-    let sysroot_dir = AbsPathBuf::assert(sysroot_path);
+    let sysroot_dir = AbsPathBuf::assert_utf8(sysroot_path);
     let sysroot_src_dir = sysroot_dir.clone();
     Sysroot::load(sysroot_dir, Some(Ok(sysroot_src_dir)), false)
 }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs
index 960f5b531d4..439b006977d 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs
@@ -903,6 +903,7 @@ fn out_dirs_check() {
 }
 
 #[test]
+#[cfg(not(windows))] // windows requires elevated permissions to create symlinks
 fn root_contains_symlink_out_dirs_check() {
     out_dirs_check_impl(true);
 }
@@ -917,7 +918,7 @@ fn resolve_proc_macro() {
     }
 
     let sysroot = project_model::Sysroot::discover_no_source(
-        &AbsPathBuf::assert(std::env::current_dir().unwrap()),
+        &AbsPathBuf::assert_utf8(std::env::current_dir().unwrap()),
         &Default::default(),
     )
     .unwrap();
@@ -1002,7 +1003,7 @@ pub fn foo(_input: TokenStream) -> TokenStream {
         },
         "procMacro": {
             "enable": true,
-            "server": proc_macro_server_path.as_path().as_ref(),
+            "server": proc_macro_server_path.as_path().as_str(),
         }
     }))
     .root("foo")
@@ -1039,7 +1040,7 @@ fn test_will_rename_files_same_level() {
 
     let tmp_dir = TestDir::new();
     let tmp_dir_path = tmp_dir.path().to_owned();
-    let tmp_dir_str = tmp_dir_path.to_str().unwrap();
+    let tmp_dir_str = tmp_dir_path.as_str();
     let base_path = PathBuf::from(format!("file://{tmp_dir_str}"));
 
     let code = r#"
@@ -1084,7 +1085,7 @@ use crate::old_folder::nested::foo as bar;
           "documentChanges": [
             {
               "textDocument": {
-                "uri": format!("file://{}", tmp_dir_path.join("src").join("lib.rs").to_str().unwrap().to_owned().replace("C:\\", "/c:/").replace('\\', "/")),
+                "uri": format!("file://{}", tmp_dir_path.join("src").join("lib.rs").as_str().to_owned().replace("C:\\", "/c:/").replace('\\', "/")),
                 "version": null
               },
               "edits": [
@@ -1141,7 +1142,7 @@ use crate::old_folder::nested::foo as bar;
           "documentChanges": [
             {
               "textDocument": {
-                "uri": format!("file://{}", tmp_dir_path.join("src").join("lib.rs").to_str().unwrap().to_owned().replace("C:\\", "/c:/").replace('\\', "/")),
+                "uri": format!("file://{}", tmp_dir_path.join("src").join("lib.rs").as_str().to_owned().replace("C:\\", "/c:/").replace('\\', "/")),
                 "version": null
               },
               "edits": [
@@ -1162,7 +1163,7 @@ use crate::old_folder::nested::foo as bar;
             },
             {
               "textDocument": {
-                "uri": format!("file://{}", tmp_dir_path.join("src").join("old_folder").join("nested.rs").to_str().unwrap().to_owned().replace("C:\\", "/c:/").replace('\\', "/")),
+                "uri": format!("file://{}", tmp_dir_path.join("src").join("old_folder").join("nested.rs").as_str().to_owned().replace("C:\\", "/c:/").replace('\\', "/")),
                 "version": null
               },
               "edits": [
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs
index 1d831b8b105..8bbe6ff3724 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/support.rs
@@ -1,7 +1,6 @@
 use std::{
     cell::{Cell, RefCell},
     fs,
-    path::{Path, PathBuf},
     sync::Once,
     time::Duration,
 };
@@ -9,6 +8,7 @@ use std::{
 use crossbeam_channel::{after, select, Receiver};
 use lsp_server::{Connection, Message, Notification, Request};
 use lsp_types::{notification::Exit, request::Shutdown, TextDocumentIdentifier, Url};
+use paths::{Utf8Path, Utf8PathBuf};
 use rust_analyzer::{config::Config, lsp, main_loop};
 use serde::Serialize;
 use serde_json::{json, to_string_pretty, Value};
@@ -21,7 +21,7 @@ use crate::testdir::TestDir;
 pub(crate) struct Project<'a> {
     fixture: &'a str,
     tmp_dir: Option<TestDir>,
-    roots: Vec<PathBuf>,
+    roots: Vec<Utf8PathBuf>,
     config: serde_json::Value,
     root_dir_contains_symlink: bool,
 }
@@ -359,7 +359,7 @@ impl Server {
         self.client.sender.send(Message::Notification(not)).unwrap();
     }
 
-    pub(crate) fn path(&self) -> &Path {
+    pub(crate) fn path(&self) -> &Utf8Path {
         self.dir.path()
     }
 }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/testdir.rs b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/testdir.rs
index b3ee7fa3d03..d113bd51278 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/testdir.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/testdir.rs
@@ -1,11 +1,12 @@
 use std::{
     fs, io,
-    path::{Path, PathBuf},
     sync::atomic::{AtomicUsize, Ordering},
 };
 
+use paths::{Utf8Path, Utf8PathBuf};
+
 pub(crate) struct TestDir {
-    path: PathBuf,
+    path: Utf8PathBuf,
     keep: bool,
 }
 
@@ -51,10 +52,13 @@ impl TestDir {
                 #[cfg(target_os = "windows")]
                 std::os::windows::fs::symlink_dir(path, &symlink_path).unwrap();
 
-                return TestDir { path: symlink_path, keep: false };
+                return TestDir {
+                    path: Utf8PathBuf::from_path_buf(symlink_path).unwrap(),
+                    keep: false,
+                };
             }
 
-            return TestDir { path, keep: false };
+            return TestDir { path: Utf8PathBuf::from_path_buf(path).unwrap(), keep: false };
         }
         panic!("Failed to create a temporary directory")
     }
@@ -64,7 +68,7 @@ impl TestDir {
         self.keep = true;
         self
     }
-    pub(crate) fn path(&self) -> &Path {
+    pub(crate) fn path(&self) -> &Utf8Path {
         &self.path
     }
 }
@@ -79,7 +83,7 @@ impl Drop for TestDir {
         let actual_path = filetype.is_symlink().then(|| fs::read_link(&self.path).unwrap());
 
         if let Some(actual_path) = actual_path {
-            remove_dir_all(&actual_path).unwrap_or_else(|err| {
+            remove_dir_all(Utf8Path::from_path(&actual_path).unwrap()).unwrap_or_else(|err| {
                 panic!(
                     "failed to remove temporary link to directory {}: {err}",
                     actual_path.display()
@@ -88,18 +92,18 @@ impl Drop for TestDir {
         }
 
         remove_dir_all(&self.path).unwrap_or_else(|err| {
-            panic!("failed to remove temporary directory {}: {err}", self.path.display())
+            panic!("failed to remove temporary directory {}: {err}", self.path)
         });
     }
 }
 
 #[cfg(not(windows))]
-fn remove_dir_all(path: &Path) -> io::Result<()> {
+fn remove_dir_all(path: &Utf8Path) -> io::Result<()> {
     fs::remove_dir_all(path)
 }
 
 #[cfg(windows)]
-fn remove_dir_all(path: &Path) -> io::Result<()> {
+fn remove_dir_all(path: &Utf8Path) -> io::Result<()> {
     for _ in 0..99 {
         if fs::remove_dir_all(path).is_ok() {
             return Ok(());
diff --git a/src/tools/rust-analyzer/crates/span/src/lib.rs b/src/tools/rust-analyzer/crates/span/src/lib.rs
index 6b849ce3738..c9109c72d0d 100644
--- a/src/tools/rust-analyzer/crates/span/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/span/src/lib.rs
@@ -16,6 +16,56 @@ pub use self::{
 pub use syntax::{TextRange, TextSize};
 pub use vfs::FileId;
 
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub enum Edition {
+    Edition2015,
+    Edition2018,
+    Edition2021,
+    Edition2024,
+}
+
+impl Edition {
+    pub const CURRENT: Edition = Edition::Edition2021;
+    pub const DEFAULT: Edition = Edition::Edition2015;
+}
+
+#[derive(Debug)]
+pub struct ParseEditionError {
+    invalid_input: String,
+}
+
+impl std::error::Error for ParseEditionError {}
+impl fmt::Display for ParseEditionError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "invalid edition: {:?}", self.invalid_input)
+    }
+}
+
+impl std::str::FromStr for Edition {
+    type Err = ParseEditionError;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        let res = match s {
+            "2015" => Edition::Edition2015,
+            "2018" => Edition::Edition2018,
+            "2021" => Edition::Edition2021,
+            "2024" => Edition::Edition2024,
+            _ => return Err(ParseEditionError { invalid_input: s.to_owned() }),
+        };
+        Ok(res)
+    }
+}
+
+impl fmt::Display for Edition {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.write_str(match self {
+            Edition::Edition2015 => "2015",
+            Edition::Edition2018 => "2018",
+            Edition::Edition2021 => "2021",
+            Edition::Edition2024 => "2024",
+        })
+    }
+}
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 pub struct FilePosition {
     pub file_id: FileId,
diff --git a/src/tools/rust-analyzer/crates/syntax/Cargo.toml b/src/tools/rust-analyzer/crates/syntax/Cargo.toml
index 9a8d73cf7ff..1809ca7dea5 100644
--- a/src/tools/rust-analyzer/crates/syntax/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/syntax/Cargo.toml
@@ -33,12 +33,8 @@ text-edit.workspace = true
 [dev-dependencies]
 rayon.workspace = true
 expect-test = "1.4.0"
-proc-macro2 = "1.0.47"
-quote = "1.0.20"
-ungrammar = "1.16.1"
 
 test-utils.workspace = true
-sourcegen.workspace = true
 
 [features]
 in-rust-tree = []
diff --git a/src/tools/rust-analyzer/crates/syntax/rust.ungram b/src/tools/rust-analyzer/crates/syntax/rust.ungram
index c3d8e97c436..e1765b25fd8 100644
--- a/src/tools/rust-analyzer/crates/syntax/rust.ungram
+++ b/src/tools/rust-analyzer/crates/syntax/rust.ungram
@@ -414,7 +414,7 @@ StmtList =
   '}'
 
 RefExpr =
-  Attr* '&' ('raw' | 'mut' | 'const') Expr
+  Attr* '&' (('raw' 'const'?)| ('raw'? 'mut') ) Expr
 
 TryExpr =
   Attr* Expr '?'
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
index 75971861aa8..c82bc4151ac 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
@@ -8,247 +8,269 @@ use crate::{
 };
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Name {
+pub struct Abi {
     pub(crate) syntax: SyntaxNode,
 }
-impl Name {
-    pub fn ident_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ident]) }
-    pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) }
+impl Abi {
+    pub fn extern_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![extern]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct NameRef {
+pub struct ArgList {
     pub(crate) syntax: SyntaxNode,
 }
-impl NameRef {
-    pub fn ident_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ident]) }
-    pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) }
-    pub fn super_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![super]) }
-    pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) }
-    pub fn Self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![Self]) }
+impl ArgList {
+    pub fn args(&self) -> AstChildren<Expr> { support::children(&self.syntax) }
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Lifetime {
+pub struct ArrayExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl Lifetime {
-    pub fn lifetime_ident_token(&self) -> Option<SyntaxToken> {
-        support::token(&self.syntax, T![lifetime_ident])
-    }
+impl ast::HasAttrs for ArrayExpr {}
+impl ArrayExpr {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn exprs(&self) -> AstChildren<Expr> { support::children(&self.syntax) }
+    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
+    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Path {
+pub struct ArrayType {
     pub(crate) syntax: SyntaxNode,
 }
-impl Path {
-    pub fn qualifier(&self) -> Option<Path> { support::child(&self.syntax) }
-    pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
-    pub fn segment(&self) -> Option<PathSegment> { support::child(&self.syntax) }
+impl ArrayType {
+    pub fn const_arg(&self) -> Option<ConstArg> { support::child(&self.syntax) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
+    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct PathSegment {
+pub struct AsmExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl PathSegment {
-    pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
-    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
-    pub fn generic_arg_list(&self) -> Option<GenericArgList> { support::child(&self.syntax) }
-    pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
-    pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
-    pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
-    pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
-    pub fn path_type(&self) -> Option<PathType> { support::child(&self.syntax) }
-    pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
+impl ast::HasAttrs for AsmExpr {}
+impl AsmExpr {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) }
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+    pub fn asm_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![asm]) }
+    pub fn builtin_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![builtin]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct GenericArgList {
+pub struct AssocItemList {
     pub(crate) syntax: SyntaxNode,
 }
-impl GenericArgList {
-    pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
-    pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
-    pub fn generic_args(&self) -> AstChildren<GenericArg> { support::children(&self.syntax) }
-    pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
+impl ast::HasAttrs for AssocItemList {}
+impl AssocItemList {
+    pub fn assoc_items(&self) -> AstChildren<AssocItem> { support::children(&self.syntax) }
+    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
+    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct ParamList {
+pub struct AssocTypeArg {
     pub(crate) syntax: SyntaxNode,
 }
-impl ParamList {
-    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
-    pub fn self_param(&self) -> Option<SelfParam> { support::child(&self.syntax) }
-    pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
-    pub fn params(&self) -> AstChildren<Param> { support::children(&self.syntax) }
-    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
-    pub fn pipe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![|]) }
+impl ast::HasTypeBounds for AssocTypeArg {}
+impl AssocTypeArg {
+    pub fn const_arg(&self) -> Option<ConstArg> { support::child(&self.syntax) }
+    pub fn generic_arg_list(&self) -> Option<GenericArgList> { support::child(&self.syntax) }
+    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
+    pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
+    pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RetType {
+pub struct Attr {
     pub(crate) syntax: SyntaxNode,
 }
-impl RetType {
-    pub fn thin_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![->]) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+impl Attr {
+    pub fn meta(&self) -> Option<Meta> { support::child(&self.syntax) }
+    pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
+    pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) }
+    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
+    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct PathType {
+pub struct AwaitExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl PathType {
-    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
+impl ast::HasAttrs for AwaitExpr {}
+impl AwaitExpr {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) }
+    pub fn await_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![await]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct TypeArg {
+pub struct BecomeExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl TypeArg {
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+impl ast::HasAttrs for BecomeExpr {}
+impl BecomeExpr {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn become_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![become]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct AssocTypeArg {
+pub struct BinExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasTypeBounds for AssocTypeArg {}
-impl AssocTypeArg {
-    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
-    pub fn generic_arg_list(&self) -> Option<GenericArgList> { support::child(&self.syntax) }
-    pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
-    pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
-    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
-    pub fn const_arg(&self) -> Option<ConstArg> { support::child(&self.syntax) }
+impl ast::HasAttrs for BinExpr {}
+impl BinExpr {}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct BlockExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::HasAttrs for BlockExpr {}
+impl BlockExpr {
+    pub fn label(&self) -> Option<Label> { support::child(&self.syntax) }
+    pub fn stmt_list(&self) -> Option<StmtList> { support::child(&self.syntax) }
+    pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
+    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
+    pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) }
+    pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct LifetimeArg {
+pub struct BoxPat {
     pub(crate) syntax: SyntaxNode,
 }
-impl LifetimeArg {
-    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
+impl BoxPat {
+    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
+    pub fn box_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![box]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct ConstArg {
+pub struct BreakExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl ConstArg {
+impl ast::HasAttrs for BreakExpr {}
+impl BreakExpr {
     pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
+    pub fn break_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![break]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct TypeBoundList {
+pub struct CallExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl TypeBoundList {
-    pub fn bounds(&self) -> AstChildren<TypeBound> { support::children(&self.syntax) }
+impl ast::HasArgList for CallExpr {}
+impl ast::HasAttrs for CallExpr {}
+impl CallExpr {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct MacroCall {
+pub struct CastExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for MacroCall {}
-impl ast::HasDocComments for MacroCall {}
-impl MacroCall {
-    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
-    pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
-    pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) }
-    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+impl ast::HasAttrs for CastExpr {}
+impl CastExpr {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Attr {
+pub struct ClosureExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl Attr {
-    pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) }
-    pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
-    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
-    pub fn meta(&self) -> Option<Meta> { support::child(&self.syntax) }
-    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
+impl ast::HasAttrs for ClosureExpr {}
+impl ClosureExpr {
+    pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
+    pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
+    pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
+    pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
+    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
+    pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
+    pub fn move_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![move]) }
+    pub fn static_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![static]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct TokenTree {
+pub struct Const {
     pub(crate) syntax: SyntaxNode,
 }
-impl TokenTree {
-    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
-    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
-    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
-    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
-    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
-    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
+impl ast::HasAttrs for Const {}
+impl ast::HasDocComments for Const {}
+impl ast::HasName for Const {}
+impl ast::HasVisibility for Const {}
+impl Const {
+    pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+    pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
+    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
+    pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct MacroItems {
+pub struct ConstArg {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasModuleItem for MacroItems {}
-impl MacroItems {}
+impl ConstArg {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+}
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct MacroEagerInput {
+pub struct ConstBlockPat {
     pub(crate) syntax: SyntaxNode,
 }
-impl MacroEagerInput {
-    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
-    pub fn exprs(&self) -> AstChildren<Expr> { support::children(&self.syntax) }
-    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
-    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
-    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
-    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
-    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
+impl ConstBlockPat {
+    pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
+    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct MacroStmts {
+pub struct ConstParam {
     pub(crate) syntax: SyntaxNode,
 }
-impl MacroStmts {
-    pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) }
-    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+impl ast::HasAttrs for ConstParam {}
+impl ast::HasName for ConstParam {}
+impl ConstParam {
+    pub fn default_val(&self) -> Option<ConstArg> { support::child(&self.syntax) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct SourceFile {
+pub struct ContinueExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for SourceFile {}
-impl ast::HasModuleItem for SourceFile {}
-impl ast::HasDocComments for SourceFile {}
-impl SourceFile {
-    pub fn shebang_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![shebang]) }
+impl ast::HasAttrs for ContinueExpr {}
+impl ContinueExpr {
+    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
+    pub fn continue_token(&self) -> Option<SyntaxToken> {
+        support::token(&self.syntax, T![continue])
+    }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Const {
+pub struct DynTraitType {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for Const {}
-impl ast::HasName for Const {}
-impl ast::HasVisibility for Const {}
-impl ast::HasDocComments for Const {}
-impl Const {
-    pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
-    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
-    pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
-    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
-    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
-    pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+impl DynTraitType {
+    pub fn type_bound_list(&self) -> Option<TypeBoundList> { support::child(&self.syntax) }
+    pub fn dyn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![dyn]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -256,13 +278,22 @@ pub struct Enum {
     pub(crate) syntax: SyntaxNode,
 }
 impl ast::HasAttrs for Enum {}
+impl ast::HasDocComments for Enum {}
+impl ast::HasGenericParams for Enum {}
 impl ast::HasName for Enum {}
 impl ast::HasVisibility for Enum {}
-impl ast::HasGenericParams for Enum {}
-impl ast::HasDocComments for Enum {}
 impl Enum {
-    pub fn enum_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![enum]) }
     pub fn variant_list(&self) -> Option<VariantList> { support::child(&self.syntax) }
+    pub fn enum_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![enum]) }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ExprStmt {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ExprStmt {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -272,9 +303,9 @@ pub struct ExternBlock {
 impl ast::HasAttrs for ExternBlock {}
 impl ast::HasDocComments for ExternBlock {}
 impl ExternBlock {
-    pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
     pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) }
     pub fn extern_item_list(&self) -> Option<ExternItemList> { support::child(&self.syntax) }
+    pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -282,14 +313,36 @@ pub struct ExternCrate {
     pub(crate) syntax: SyntaxNode,
 }
 impl ast::HasAttrs for ExternCrate {}
-impl ast::HasVisibility for ExternCrate {}
 impl ast::HasDocComments for ExternCrate {}
+impl ast::HasVisibility for ExternCrate {}
 impl ExternCrate {
-    pub fn extern_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![extern]) }
-    pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) }
     pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
     pub fn rename(&self) -> Option<Rename> { support::child(&self.syntax) }
     pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+    pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) }
+    pub fn extern_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![extern]) }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct ExternItemList {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::HasAttrs for ExternItemList {}
+impl ExternItemList {
+    pub fn extern_items(&self) -> AstChildren<ExternItem> { support::children(&self.syntax) }
+    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
+    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct FieldExpr {
+    pub(crate) syntax: SyntaxNode,
+}
+impl ast::HasAttrs for FieldExpr {}
+impl FieldExpr {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
+    pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -297,769 +350,659 @@ pub struct Fn {
     pub(crate) syntax: SyntaxNode,
 }
 impl ast::HasAttrs for Fn {}
+impl ast::HasDocComments for Fn {}
+impl ast::HasGenericParams for Fn {}
 impl ast::HasName for Fn {}
 impl ast::HasVisibility for Fn {}
-impl ast::HasGenericParams for Fn {}
-impl ast::HasDocComments for Fn {}
 impl Fn {
-    pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
-    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
-    pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
-    pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
     pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) }
-    pub fn fn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![fn]) }
+    pub fn body(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
     pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
     pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
-    pub fn body(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
     pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Impl {
-    pub(crate) syntax: SyntaxNode,
-}
-impl ast::HasAttrs for Impl {}
-impl ast::HasVisibility for Impl {}
-impl ast::HasGenericParams for Impl {}
-impl ast::HasDocComments for Impl {}
-impl Impl {
+    pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
+    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
     pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
+    pub fn fn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![fn]) }
     pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
-    pub fn impl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![impl]) }
-    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
-    pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
-    pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
-    pub fn assoc_item_list(&self) -> Option<AssocItemList> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct MacroRules {
+pub struct FnPtrType {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for MacroRules {}
-impl ast::HasName for MacroRules {}
-impl ast::HasVisibility for MacroRules {}
-impl ast::HasDocComments for MacroRules {}
-impl MacroRules {
-    pub fn macro_rules_token(&self) -> Option<SyntaxToken> {
-        support::token(&self.syntax, T![macro_rules])
-    }
-    pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
-    pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) }
+impl FnPtrType {
+    pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) }
+    pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
+    pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
+    pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
+    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
+    pub fn fn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![fn]) }
+    pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct MacroDef {
+pub struct ForExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for MacroDef {}
-impl ast::HasName for MacroDef {}
-impl ast::HasVisibility for MacroDef {}
-impl ast::HasDocComments for MacroDef {}
-impl MacroDef {
-    pub fn macro_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![macro]) }
-    pub fn args(&self) -> Option<TokenTree> { support::child(&self.syntax) }
-    pub fn body(&self) -> Option<TokenTree> { support::child(&self.syntax) }
+impl ast::HasAttrs for ForExpr {}
+impl ForExpr {
+    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
+    pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
+    pub fn in_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![in]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Module {
+pub struct ForType {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for Module {}
-impl ast::HasName for Module {}
-impl ast::HasVisibility for Module {}
-impl ast::HasDocComments for Module {}
-impl Module {
-    pub fn mod_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mod]) }
-    pub fn item_list(&self) -> Option<ItemList> { support::child(&self.syntax) }
-    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+impl ForType {
+    pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Static {
+pub struct FormatArgsArg {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for Static {}
-impl ast::HasName for Static {}
-impl ast::HasVisibility for Static {}
-impl ast::HasDocComments for Static {}
-impl Static {
-    pub fn static_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![static]) }
-    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
-    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+impl ast::HasName for FormatArgsArg {}
+impl FormatArgsArg {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
     pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
-    pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Struct {
+pub struct FormatArgsExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for Struct {}
-impl ast::HasName for Struct {}
-impl ast::HasVisibility for Struct {}
-impl ast::HasGenericParams for Struct {}
-impl ast::HasDocComments for Struct {}
-impl Struct {
-    pub fn struct_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![struct]) }
-    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
-    pub fn field_list(&self) -> Option<FieldList> { support::child(&self.syntax) }
+impl ast::HasAttrs for FormatArgsExpr {}
+impl FormatArgsExpr {
+    pub fn args(&self) -> AstChildren<FormatArgsArg> { support::children(&self.syntax) }
+    pub fn template(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) }
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+    pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
+    pub fn builtin_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![builtin]) }
+    pub fn format_args_token(&self) -> Option<SyntaxToken> {
+        support::token(&self.syntax, T![format_args])
+    }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Trait {
+pub struct GenericArgList {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for Trait {}
-impl ast::HasName for Trait {}
-impl ast::HasVisibility for Trait {}
-impl ast::HasGenericParams for Trait {}
-impl ast::HasTypeBounds for Trait {}
-impl ast::HasDocComments for Trait {}
-impl Trait {
-    pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
-    pub fn auto_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![auto]) }
-    pub fn trait_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![trait]) }
-    pub fn assoc_item_list(&self) -> Option<AssocItemList> { support::child(&self.syntax) }
+impl GenericArgList {
+    pub fn generic_args(&self) -> AstChildren<GenericArg> { support::children(&self.syntax) }
+    pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
+    pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
+    pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct TraitAlias {
+pub struct GenericParamList {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for TraitAlias {}
-impl ast::HasName for TraitAlias {}
-impl ast::HasVisibility for TraitAlias {}
-impl ast::HasGenericParams for TraitAlias {}
-impl ast::HasDocComments for TraitAlias {}
-impl TraitAlias {
-    pub fn trait_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![trait]) }
-    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
-    pub fn type_bound_list(&self) -> Option<TypeBoundList> { support::child(&self.syntax) }
-    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+impl GenericParamList {
+    pub fn generic_params(&self) -> AstChildren<GenericParam> { support::children(&self.syntax) }
+    pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
+    pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct TypeAlias {
+pub struct IdentPat {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for TypeAlias {}
-impl ast::HasName for TypeAlias {}
-impl ast::HasVisibility for TypeAlias {}
-impl ast::HasGenericParams for TypeAlias {}
-impl ast::HasTypeBounds for TypeAlias {}
-impl ast::HasDocComments for TypeAlias {}
-impl TypeAlias {
-    pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
-    pub fn type_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![type]) }
-    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
-    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+impl ast::HasAttrs for IdentPat {}
+impl ast::HasName for IdentPat {}
+impl IdentPat {
+    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
+    pub fn at_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![@]) }
+    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
+    pub fn ref_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ref]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Union {
+pub struct IfExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for Union {}
-impl ast::HasName for Union {}
-impl ast::HasVisibility for Union {}
-impl ast::HasGenericParams for Union {}
-impl ast::HasDocComments for Union {}
-impl Union {
-    pub fn union_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![union]) }
-    pub fn record_field_list(&self) -> Option<RecordFieldList> { support::child(&self.syntax) }
+impl ast::HasAttrs for IfExpr {}
+impl IfExpr {
+    pub fn else_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![else]) }
+    pub fn if_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![if]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Use {
+pub struct Impl {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for Use {}
-impl ast::HasVisibility for Use {}
-impl ast::HasDocComments for Use {}
-impl Use {
-    pub fn use_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![use]) }
-    pub fn use_tree(&self) -> Option<UseTree> { support::child(&self.syntax) }
-    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+impl ast::HasAttrs for Impl {}
+impl ast::HasDocComments for Impl {}
+impl ast::HasGenericParams for Impl {}
+impl ast::HasVisibility for Impl {}
+impl Impl {
+    pub fn assoc_item_list(&self) -> Option<AssocItemList> { support::child(&self.syntax) }
+    pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
+    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
+    pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
+    pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
+    pub fn impl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![impl]) }
+    pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Visibility {
+pub struct ImplTraitType {
     pub(crate) syntax: SyntaxNode,
 }
-impl Visibility {
-    pub fn pub_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![pub]) }
-    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
-    pub fn in_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![in]) }
-    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
-    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+impl ImplTraitType {
+    pub fn type_bound_list(&self) -> Option<TypeBoundList> { support::child(&self.syntax) }
+    pub fn impl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![impl]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct ItemList {
+pub struct IndexExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for ItemList {}
-impl ast::HasModuleItem for ItemList {}
-impl ItemList {
-    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
-    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+impl ast::HasAttrs for IndexExpr {}
+impl IndexExpr {
+    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
+    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Rename {
+pub struct InferType {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasName for Rename {}
-impl Rename {
-    pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
+impl InferType {
     pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct UseTree {
-    pub(crate) syntax: SyntaxNode,
-}
-impl UseTree {
-    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
-    pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
-    pub fn star_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![*]) }
-    pub fn use_tree_list(&self) -> Option<UseTreeList> { support::child(&self.syntax) }
-    pub fn rename(&self) -> Option<Rename> { support::child(&self.syntax) }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct UseTreeList {
+pub struct ItemList {
     pub(crate) syntax: SyntaxNode,
 }
-impl UseTreeList {
+impl ast::HasAttrs for ItemList {}
+impl ast::HasModuleItem for ItemList {}
+impl ItemList {
     pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
-    pub fn use_trees(&self) -> AstChildren<UseTree> { support::children(&self.syntax) }
     pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Abi {
-    pub(crate) syntax: SyntaxNode,
-}
-impl Abi {
-    pub fn extern_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![extern]) }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct GenericParamList {
+pub struct Label {
     pub(crate) syntax: SyntaxNode,
 }
-impl GenericParamList {
-    pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
-    pub fn generic_params(&self) -> AstChildren<GenericParam> { support::children(&self.syntax) }
-    pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
+impl Label {
+    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
+    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct WhereClause {
+pub struct LetElse {
     pub(crate) syntax: SyntaxNode,
 }
-impl WhereClause {
-    pub fn where_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![where]) }
-    pub fn predicates(&self) -> AstChildren<WherePred> { support::children(&self.syntax) }
+impl LetElse {
+    pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
+    pub fn else_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![else]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct BlockExpr {
+pub struct LetExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for BlockExpr {}
-impl BlockExpr {
-    pub fn label(&self) -> Option<Label> { support::child(&self.syntax) }
-    pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) }
-    pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
-    pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
-    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
-    pub fn stmt_list(&self) -> Option<StmtList> { support::child(&self.syntax) }
+impl ast::HasAttrs for LetExpr {}
+impl LetExpr {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+    pub fn let_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![let]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct SelfParam {
+pub struct LetStmt {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for SelfParam {}
-impl ast::HasName for SelfParam {}
-impl SelfParam {
-    pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
-    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
-    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
-    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
+impl ast::HasAttrs for LetStmt {}
+impl LetStmt {
+    pub fn initializer(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn let_else(&self) -> Option<LetElse> { support::child(&self.syntax) }
+    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
     pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+    pub fn let_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![let]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Param {
+pub struct Lifetime {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for Param {}
-impl Param {
-    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
-    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
-    pub fn dotdotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![...]) }
+impl Lifetime {
+    pub fn lifetime_ident_token(&self) -> Option<SyntaxToken> {
+        support::token(&self.syntax, T![lifetime_ident])
+    }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RecordFieldList {
+pub struct LifetimeArg {
     pub(crate) syntax: SyntaxNode,
 }
-impl RecordFieldList {
-    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
-    pub fn fields(&self) -> AstChildren<RecordField> { support::children(&self.syntax) }
-    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+impl LifetimeArg {
+    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct TupleFieldList {
+pub struct LifetimeParam {
     pub(crate) syntax: SyntaxNode,
 }
-impl TupleFieldList {
-    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
-    pub fn fields(&self) -> AstChildren<TupleField> { support::children(&self.syntax) }
-    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+impl ast::HasAttrs for LifetimeParam {}
+impl ast::HasTypeBounds for LifetimeParam {}
+impl LifetimeParam {
+    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RecordField {
+pub struct Literal {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for RecordField {}
-impl ast::HasName for RecordField {}
-impl ast::HasVisibility for RecordField {}
-impl ast::HasDocComments for RecordField {}
-impl RecordField {
-    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
-}
+impl ast::HasAttrs for Literal {}
+impl Literal {}
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct TupleField {
+pub struct LiteralPat {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for TupleField {}
-impl ast::HasVisibility for TupleField {}
-impl ast::HasDocComments for TupleField {}
-impl TupleField {
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+impl LiteralPat {
+    pub fn literal(&self) -> Option<Literal> { support::child(&self.syntax) }
+    pub fn minus_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![-]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct VariantList {
+pub struct LoopExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl VariantList {
-    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
-    pub fn variants(&self) -> AstChildren<Variant> { support::children(&self.syntax) }
-    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+impl ast::HasAttrs for LoopExpr {}
+impl ast::HasLoopBody for LoopExpr {}
+impl LoopExpr {
+    pub fn loop_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![loop]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Variant {
+pub struct MacroCall {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for Variant {}
-impl ast::HasName for Variant {}
-impl ast::HasVisibility for Variant {}
-impl ast::HasDocComments for Variant {}
-impl Variant {
-    pub fn field_list(&self) -> Option<FieldList> { support::child(&self.syntax) }
-    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
-    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+impl ast::HasAttrs for MacroCall {}
+impl ast::HasDocComments for MacroCall {}
+impl MacroCall {
+    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
+    pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) }
+    pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct AssocItemList {
+pub struct MacroDef {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for AssocItemList {}
-impl AssocItemList {
-    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
-    pub fn assoc_items(&self) -> AstChildren<AssocItem> { support::children(&self.syntax) }
-    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+impl ast::HasAttrs for MacroDef {}
+impl ast::HasDocComments for MacroDef {}
+impl ast::HasName for MacroDef {}
+impl ast::HasVisibility for MacroDef {}
+impl MacroDef {
+    pub fn args(&self) -> Option<TokenTree> { support::child(&self.syntax) }
+    pub fn body(&self) -> Option<TokenTree> { support::child(&self.syntax) }
+    pub fn macro_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![macro]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct ExternItemList {
+pub struct MacroEagerInput {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for ExternItemList {}
-impl ExternItemList {
+impl MacroEagerInput {
+    pub fn exprs(&self) -> AstChildren<Expr> { support::children(&self.syntax) }
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
+    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
     pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
-    pub fn extern_items(&self) -> AstChildren<ExternItem> { support::children(&self.syntax) }
     pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct ConstParam {
+pub struct MacroExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for ConstParam {}
-impl ast::HasName for ConstParam {}
-impl ConstParam {
-    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
-    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
-    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
-    pub fn default_val(&self) -> Option<ConstArg> { support::child(&self.syntax) }
+impl MacroExpr {
+    pub fn macro_call(&self) -> Option<MacroCall> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct LifetimeParam {
+pub struct MacroItems {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for LifetimeParam {}
-impl ast::HasTypeBounds for LifetimeParam {}
-impl LifetimeParam {
-    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
-}
+impl ast::HasModuleItem for MacroItems {}
+impl MacroItems {}
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct TypeParam {
+pub struct MacroPat {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for TypeParam {}
-impl ast::HasName for TypeParam {}
-impl ast::HasTypeBounds for TypeParam {}
-impl TypeParam {
-    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
-    pub fn default_type(&self) -> Option<Type> { support::child(&self.syntax) }
+impl MacroPat {
+    pub fn macro_call(&self) -> Option<MacroCall> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct WherePred {
+pub struct MacroRules {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasTypeBounds for WherePred {}
-impl WherePred {
-    pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
-    pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
-    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+impl ast::HasAttrs for MacroRules {}
+impl ast::HasDocComments for MacroRules {}
+impl ast::HasName for MacroRules {}
+impl ast::HasVisibility for MacroRules {}
+impl MacroRules {
+    pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) }
+    pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
+    pub fn macro_rules_token(&self) -> Option<SyntaxToken> {
+        support::token(&self.syntax, T![macro_rules])
+    }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Meta {
+pub struct MacroStmts {
     pub(crate) syntax: SyntaxNode,
 }
-impl Meta {
-    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
-    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+impl MacroStmts {
     pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) }
+    pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct ExprStmt {
+pub struct MacroType {
     pub(crate) syntax: SyntaxNode,
 }
-impl ExprStmt {
-    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+impl MacroType {
+    pub fn macro_call(&self) -> Option<MacroCall> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct LetStmt {
+pub struct MatchArm {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for LetStmt {}
-impl LetStmt {
-    pub fn let_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![let]) }
+impl ast::HasAttrs for MatchArm {}
+impl MatchArm {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn guard(&self) -> Option<MatchGuard> { support::child(&self.syntax) }
     pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
-    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
-    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
-    pub fn initializer(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn let_else(&self) -> Option<LetElse> { support::child(&self.syntax) }
-    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+    pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
+    pub fn fat_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=>]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct LetElse {
+pub struct MatchArmList {
     pub(crate) syntax: SyntaxNode,
 }
-impl LetElse {
-    pub fn else_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![else]) }
-    pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
+impl ast::HasAttrs for MatchArmList {}
+impl MatchArmList {
+    pub fn arms(&self) -> AstChildren<MatchArm> { support::children(&self.syntax) }
+    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
+    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct ArrayExpr {
+pub struct MatchExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for ArrayExpr {}
-impl ArrayExpr {
-    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
-    pub fn exprs(&self) -> AstChildren<Expr> { support::children(&self.syntax) }
+impl ast::HasAttrs for MatchExpr {}
+impl MatchExpr {
     pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
-    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
+    pub fn match_arm_list(&self) -> Option<MatchArmList> { support::child(&self.syntax) }
+    pub fn match_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![match]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct AsmExpr {
+pub struct MatchGuard {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for AsmExpr {}
-impl AsmExpr {
-    pub fn builtin_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![builtin]) }
-    pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) }
-    pub fn asm_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![asm]) }
-    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
-    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+impl MatchGuard {
+    pub fn if_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![if]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct AwaitExpr {
+pub struct Meta {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for AwaitExpr {}
-impl AwaitExpr {
+impl Meta {
     pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) }
-    pub fn await_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![await]) }
+    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
+    pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct BinExpr {
+pub struct MethodCallExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for BinExpr {}
-impl BinExpr {}
+impl ast::HasArgList for MethodCallExpr {}
+impl ast::HasAttrs for MethodCallExpr {}
+impl MethodCallExpr {
+    pub fn generic_arg_list(&self) -> Option<GenericArgList> { support::child(&self.syntax) }
+    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
+    pub fn receiver(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) }
+}
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct BreakExpr {
+pub struct Module {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for BreakExpr {}
-impl BreakExpr {
-    pub fn break_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![break]) }
-    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
-    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+impl ast::HasAttrs for Module {}
+impl ast::HasDocComments for Module {}
+impl ast::HasName for Module {}
+impl ast::HasVisibility for Module {}
+impl Module {
+    pub fn item_list(&self) -> Option<ItemList> { support::child(&self.syntax) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+    pub fn mod_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mod]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct CallExpr {
+pub struct Name {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for CallExpr {}
-impl ast::HasArgList for CallExpr {}
-impl CallExpr {
-    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+impl Name {
+    pub fn ident_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ident]) }
+    pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct CastExpr {
+pub struct NameRef {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for CastExpr {}
-impl CastExpr {
-    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+impl NameRef {
+    pub fn Self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![Self]) }
+    pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) }
+    pub fn ident_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ident]) }
+    pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) }
+    pub fn super_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![super]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct ClosureExpr {
+pub struct NeverType {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for ClosureExpr {}
-impl ClosureExpr {
-    pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
-    pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
-    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
-    pub fn static_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![static]) }
-    pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
-    pub fn move_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![move]) }
-    pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
-    pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
-    pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) }
+impl NeverType {
+    pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct ContinueExpr {
+pub struct OffsetOfExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for ContinueExpr {}
-impl ContinueExpr {
-    pub fn continue_token(&self) -> Option<SyntaxToken> {
-        support::token(&self.syntax, T![continue])
+impl ast::HasAttrs for OffsetOfExpr {}
+impl OffsetOfExpr {
+    pub fn fields(&self) -> AstChildren<NameRef> { support::children(&self.syntax) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) }
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+    pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
+    pub fn builtin_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![builtin]) }
+    pub fn offset_of_token(&self) -> Option<SyntaxToken> {
+        support::token(&self.syntax, T![offset_of])
     }
-    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct FieldExpr {
+pub struct OrPat {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for FieldExpr {}
-impl FieldExpr {
-    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) }
-    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
+impl OrPat {
+    pub fn pats(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct ForExpr {
+pub struct Param {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for ForExpr {}
-impl ForExpr {
-    pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
+impl ast::HasAttrs for Param {}
+impl Param {
     pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
-    pub fn in_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![in]) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn dotdotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![...]) }
+    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct FormatArgsExpr {
+pub struct ParamList {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for FormatArgsExpr {}
-impl FormatArgsExpr {
-    pub fn builtin_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![builtin]) }
-    pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) }
-    pub fn format_args_token(&self) -> Option<SyntaxToken> {
-        support::token(&self.syntax, T![format_args])
-    }
+impl ParamList {
+    pub fn params(&self) -> AstChildren<Param> { support::children(&self.syntax) }
+    pub fn self_param(&self) -> Option<SelfParam> { support::child(&self.syntax) }
     pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
-    pub fn template(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
-    pub fn args(&self) -> AstChildren<FormatArgsArg> { support::children(&self.syntax) }
     pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+    pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
+    pub fn pipe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![|]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct IfExpr {
+pub struct ParenExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for IfExpr {}
-impl IfExpr {
-    pub fn if_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![if]) }
-    pub fn else_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![else]) }
+impl ast::HasAttrs for ParenExpr {}
+impl ParenExpr {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct IndexExpr {
+pub struct ParenPat {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for IndexExpr {}
-impl IndexExpr {
-    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
-    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
+impl ParenPat {
+    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Literal {
+pub struct ParenType {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for Literal {}
-impl Literal {}
+impl ParenType {
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+}
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct LoopExpr {
+pub struct Path {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for LoopExpr {}
-impl ast::HasLoopBody for LoopExpr {}
-impl LoopExpr {
-    pub fn loop_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![loop]) }
+impl Path {
+    pub fn qualifier(&self) -> Option<Path> { support::child(&self.syntax) }
+    pub fn segment(&self) -> Option<PathSegment> { support::child(&self.syntax) }
+    pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct MacroExpr {
+pub struct PathExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl MacroExpr {
-    pub fn macro_call(&self) -> Option<MacroCall> { support::child(&self.syntax) }
+impl ast::HasAttrs for PathExpr {}
+impl PathExpr {
+    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct MatchExpr {
+pub struct PathPat {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for MatchExpr {}
-impl MatchExpr {
-    pub fn match_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![match]) }
-    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn match_arm_list(&self) -> Option<MatchArmList> { support::child(&self.syntax) }
+impl PathPat {
+    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct MethodCallExpr {
+pub struct PathSegment {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for MethodCallExpr {}
-impl ast::HasArgList for MethodCallExpr {}
-impl MethodCallExpr {
-    pub fn receiver(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) }
-    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
+impl PathSegment {
     pub fn generic_arg_list(&self) -> Option<GenericArgList> { support::child(&self.syntax) }
+    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
+    pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
+    pub fn path_type(&self) -> Option<PathType> { support::child(&self.syntax) }
+    pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
+    pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
+    pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
+    pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct OffsetOfExpr {
+pub struct PathType {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for OffsetOfExpr {}
-impl OffsetOfExpr {
-    pub fn builtin_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![builtin]) }
-    pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) }
-    pub fn offset_of_token(&self) -> Option<SyntaxToken> {
-        support::token(&self.syntax, T![offset_of])
-    }
-    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
-    pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
-    pub fn fields(&self) -> AstChildren<NameRef> { support::children(&self.syntax) }
-    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+impl PathType {
+    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct ParenExpr {
+pub struct PrefixExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for ParenExpr {}
-impl ParenExpr {
-    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+impl ast::HasAttrs for PrefixExpr {}
+impl PrefixExpr {
     pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct PathExpr {
+pub struct PtrType {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for PathExpr {}
-impl PathExpr {
-    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
+impl PtrType {
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn star_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![*]) }
+    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
+    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct PrefixExpr {
+pub struct RangeExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for PrefixExpr {}
-impl PrefixExpr {
-    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
-}
+impl ast::HasAttrs for RangeExpr {}
+impl RangeExpr {}
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RangeExpr {
+pub struct RangePat {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for RangeExpr {}
-impl RangeExpr {}
+impl RangePat {}
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct RecordExpr {
@@ -1073,325 +1016,354 @@ impl RecordExpr {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RefExpr {
+pub struct RecordExprField {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for RefExpr {}
-impl RefExpr {
-    pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
-    pub fn raw_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![raw]) }
-    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
-    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
+impl ast::HasAttrs for RecordExprField {}
+impl RecordExprField {
     pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
+    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct ReturnExpr {
+pub struct RecordExprFieldList {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for ReturnExpr {}
-impl ReturnExpr {
-    pub fn return_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![return]) }
-    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+impl ast::HasAttrs for RecordExprFieldList {}
+impl RecordExprFieldList {
+    pub fn fields(&self) -> AstChildren<RecordExprField> { support::children(&self.syntax) }
+    pub fn spread(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
+    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+    pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct BecomeExpr {
+pub struct RecordField {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for BecomeExpr {}
-impl BecomeExpr {
-    pub fn become_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![become]) }
-    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+impl ast::HasAttrs for RecordField {}
+impl ast::HasDocComments for RecordField {}
+impl ast::HasName for RecordField {}
+impl ast::HasVisibility for RecordField {}
+impl RecordField {
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct TryExpr {
+pub struct RecordFieldList {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for TryExpr {}
-impl TryExpr {
-    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn question_mark_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![?]) }
+impl RecordFieldList {
+    pub fn fields(&self) -> AstChildren<RecordField> { support::children(&self.syntax) }
+    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
+    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct TupleExpr {
+pub struct RecordPat {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for TupleExpr {}
-impl TupleExpr {
-    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
-    pub fn fields(&self) -> AstChildren<Expr> { support::children(&self.syntax) }
-    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+impl RecordPat {
+    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
+    pub fn record_pat_field_list(&self) -> Option<RecordPatFieldList> {
+        support::child(&self.syntax)
+    }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct WhileExpr {
+pub struct RecordPatField {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for WhileExpr {}
-impl WhileExpr {
-    pub fn while_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![while]) }
+impl ast::HasAttrs for RecordPatField {}
+impl RecordPatField {
+    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
+    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
+    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct YieldExpr {
+pub struct RecordPatFieldList {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for YieldExpr {}
-impl YieldExpr {
-    pub fn yield_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![yield]) }
-    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+impl RecordPatFieldList {
+    pub fn fields(&self) -> AstChildren<RecordPatField> { support::children(&self.syntax) }
+    pub fn rest_pat(&self) -> Option<RestPat> { support::child(&self.syntax) }
+    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
+    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct YeetExpr {
+pub struct RefExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for YeetExpr {}
-impl YeetExpr {
-    pub fn do_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![do]) }
-    pub fn yeet_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![yeet]) }
+impl ast::HasAttrs for RefExpr {}
+impl RefExpr {
     pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
+    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
+    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
+    pub fn raw_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![raw]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct LetExpr {
+pub struct RefPat {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for LetExpr {}
-impl LetExpr {
-    pub fn let_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![let]) }
+impl RefPat {
     pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
-    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
-    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct UnderscoreExpr {
-    pub(crate) syntax: SyntaxNode,
-}
-impl ast::HasAttrs for UnderscoreExpr {}
-impl UnderscoreExpr {
-    pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
+    pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
+    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct FormatArgsArg {
+pub struct RefType {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasName for FormatArgsArg {}
-impl FormatArgsArg {
-    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
-    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+impl RefType {
+    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
+    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct StmtList {
+pub struct Rename {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for StmtList {}
-impl StmtList {
-    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
-    pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) }
-    pub fn tail_expr(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+impl ast::HasName for Rename {}
+impl Rename {
+    pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
+    pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Label {
+pub struct RestPat {
     pub(crate) syntax: SyntaxNode,
 }
-impl Label {
-    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
-    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
+impl ast::HasAttrs for RestPat {}
+impl RestPat {
+    pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RecordExprFieldList {
+pub struct RetType {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for RecordExprFieldList {}
-impl RecordExprFieldList {
-    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
-    pub fn fields(&self) -> AstChildren<RecordExprField> { support::children(&self.syntax) }
-    pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
-    pub fn spread(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+impl RetType {
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn thin_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![->]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RecordExprField {
+pub struct ReturnExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for RecordExprField {}
-impl RecordExprField {
-    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
-    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
+impl ast::HasAttrs for ReturnExpr {}
+impl ReturnExpr {
     pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn return_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![return]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct ArgList {
+pub struct SelfParam {
     pub(crate) syntax: SyntaxNode,
 }
-impl ArgList {
-    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
-    pub fn args(&self) -> AstChildren<Expr> { support::children(&self.syntax) }
-    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+impl ast::HasAttrs for SelfParam {}
+impl ast::HasName for SelfParam {}
+impl SelfParam {
+    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
+    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
+    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct MatchArmList {
+pub struct SlicePat {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for MatchArmList {}
-impl MatchArmList {
-    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
-    pub fn arms(&self) -> AstChildren<MatchArm> { support::children(&self.syntax) }
-    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+impl SlicePat {
+    pub fn pats(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
+    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
+    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct MatchArm {
+pub struct SliceType {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for MatchArm {}
-impl MatchArm {
-    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
-    pub fn guard(&self) -> Option<MatchGuard> { support::child(&self.syntax) }
-    pub fn fat_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=>]) }
-    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
-    pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
+impl SliceType {
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
+    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct MatchGuard {
+pub struct SourceFile {
     pub(crate) syntax: SyntaxNode,
 }
-impl MatchGuard {
-    pub fn if_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![if]) }
+impl ast::HasAttrs for SourceFile {}
+impl ast::HasDocComments for SourceFile {}
+impl ast::HasModuleItem for SourceFile {}
+impl SourceFile {
+    pub fn shebang_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![shebang]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct ArrayType {
+pub struct Static {
     pub(crate) syntax: SyntaxNode,
 }
-impl ArrayType {
-    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
+impl ast::HasAttrs for Static {}
+impl ast::HasDocComments for Static {}
+impl ast::HasName for Static {}
+impl ast::HasVisibility for Static {}
+impl Static {
+    pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) }
     pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
     pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
-    pub fn const_arg(&self) -> Option<ConstArg> { support::child(&self.syntax) }
-    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
+    pub fn static_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![static]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct DynTraitType {
+pub struct StmtList {
     pub(crate) syntax: SyntaxNode,
 }
-impl DynTraitType {
-    pub fn dyn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![dyn]) }
-    pub fn type_bound_list(&self) -> Option<TypeBoundList> { support::child(&self.syntax) }
+impl ast::HasAttrs for StmtList {}
+impl StmtList {
+    pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) }
+    pub fn tail_expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
+    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct FnPtrType {
+pub struct Struct {
     pub(crate) syntax: SyntaxNode,
 }
-impl FnPtrType {
-    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
-    pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
-    pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
-    pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) }
-    pub fn fn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![fn]) }
-    pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
-    pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
+impl ast::HasAttrs for Struct {}
+impl ast::HasDocComments for Struct {}
+impl ast::HasGenericParams for Struct {}
+impl ast::HasName for Struct {}
+impl ast::HasVisibility for Struct {}
+impl Struct {
+    pub fn field_list(&self) -> Option<FieldList> { support::child(&self.syntax) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+    pub fn struct_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![struct]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct ForType {
+pub struct TokenTree {
     pub(crate) syntax: SyntaxNode,
 }
-impl ForType {
-    pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
-    pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+impl TokenTree {
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
+    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
+    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
+    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct ImplTraitType {
+pub struct Trait {
     pub(crate) syntax: SyntaxNode,
 }
-impl ImplTraitType {
-    pub fn impl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![impl]) }
-    pub fn type_bound_list(&self) -> Option<TypeBoundList> { support::child(&self.syntax) }
+impl ast::HasAttrs for Trait {}
+impl ast::HasDocComments for Trait {}
+impl ast::HasGenericParams for Trait {}
+impl ast::HasName for Trait {}
+impl ast::HasTypeBounds for Trait {}
+impl ast::HasVisibility for Trait {}
+impl Trait {
+    pub fn assoc_item_list(&self) -> Option<AssocItemList> { support::child(&self.syntax) }
+    pub fn auto_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![auto]) }
+    pub fn trait_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![trait]) }
+    pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct InferType {
+pub struct TraitAlias {
     pub(crate) syntax: SyntaxNode,
 }
-impl InferType {
-    pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
+impl ast::HasAttrs for TraitAlias {}
+impl ast::HasDocComments for TraitAlias {}
+impl ast::HasGenericParams for TraitAlias {}
+impl ast::HasName for TraitAlias {}
+impl ast::HasVisibility for TraitAlias {}
+impl TraitAlias {
+    pub fn type_bound_list(&self) -> Option<TypeBoundList> { support::child(&self.syntax) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+    pub fn trait_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![trait]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct MacroType {
+pub struct TryExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl MacroType {
-    pub fn macro_call(&self) -> Option<MacroCall> { support::child(&self.syntax) }
+impl ast::HasAttrs for TryExpr {}
+impl TryExpr {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn question_mark_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![?]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct NeverType {
+pub struct TupleExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl NeverType {
-    pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
+impl ast::HasAttrs for TupleExpr {}
+impl TupleExpr {
+    pub fn fields(&self) -> AstChildren<Expr> { support::children(&self.syntax) }
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct ParenType {
+pub struct TupleField {
     pub(crate) syntax: SyntaxNode,
 }
-impl ParenType {
-    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+impl ast::HasAttrs for TupleField {}
+impl ast::HasDocComments for TupleField {}
+impl ast::HasVisibility for TupleField {}
+impl TupleField {
     pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
-    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct PtrType {
+pub struct TupleFieldList {
     pub(crate) syntax: SyntaxNode,
 }
-impl PtrType {
-    pub fn star_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![*]) }
-    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
-    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+impl TupleFieldList {
+    pub fn fields(&self) -> AstChildren<TupleField> { support::children(&self.syntax) }
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RefType {
+pub struct TuplePat {
     pub(crate) syntax: SyntaxNode,
 }
-impl RefType {
-    pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
-    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
-    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+impl TuplePat {
+    pub fn fields(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct SliceType {
+pub struct TupleStructPat {
     pub(crate) syntax: SyntaxNode,
 }
-impl SliceType {
-    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
-    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
-    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
+impl TupleStructPat {
+    pub fn fields(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
+    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1399,226 +1371,251 @@ pub struct TupleType {
     pub(crate) syntax: SyntaxNode,
 }
 impl TupleType {
-    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
     pub fn fields(&self) -> AstChildren<Type> { support::children(&self.syntax) }
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
     pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct TypeBound {
+pub struct TypeAlias {
     pub(crate) syntax: SyntaxNode,
 }
-impl TypeBound {
-    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
-    pub fn tilde_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![~]) }
-    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
-    pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
-    pub fn question_mark_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![?]) }
+impl ast::HasAttrs for TypeAlias {}
+impl ast::HasDocComments for TypeAlias {}
+impl ast::HasGenericParams for TypeAlias {}
+impl ast::HasName for TypeAlias {}
+impl ast::HasTypeBounds for TypeAlias {}
+impl ast::HasVisibility for TypeAlias {}
+impl TypeAlias {
     pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+    pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
+    pub fn type_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![type]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct IdentPat {
+pub struct TypeArg {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for IdentPat {}
-impl ast::HasName for IdentPat {}
-impl IdentPat {
-    pub fn ref_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ref]) }
-    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
-    pub fn at_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![@]) }
-    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
+impl TypeArg {
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct BoxPat {
+pub struct TypeBound {
     pub(crate) syntax: SyntaxNode,
 }
-impl BoxPat {
-    pub fn box_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![box]) }
-    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
+impl TypeBound {
+    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn question_mark_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![?]) }
+    pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
+    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
+    pub fn tilde_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![~]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RestPat {
+pub struct TypeBoundList {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for RestPat {}
-impl RestPat {
-    pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
+impl TypeBoundList {
+    pub fn bounds(&self) -> AstChildren<TypeBound> { support::children(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct LiteralPat {
+pub struct TypeParam {
     pub(crate) syntax: SyntaxNode,
 }
-impl LiteralPat {
-    pub fn minus_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![-]) }
-    pub fn literal(&self) -> Option<Literal> { support::child(&self.syntax) }
+impl ast::HasAttrs for TypeParam {}
+impl ast::HasName for TypeParam {}
+impl ast::HasTypeBounds for TypeParam {}
+impl TypeParam {
+    pub fn default_type(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct MacroPat {
+pub struct UnderscoreExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl MacroPat {
-    pub fn macro_call(&self) -> Option<MacroCall> { support::child(&self.syntax) }
+impl ast::HasAttrs for UnderscoreExpr {}
+impl UnderscoreExpr {
+    pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct OrPat {
+pub struct Union {
     pub(crate) syntax: SyntaxNode,
 }
-impl OrPat {
-    pub fn pats(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
+impl ast::HasAttrs for Union {}
+impl ast::HasDocComments for Union {}
+impl ast::HasGenericParams for Union {}
+impl ast::HasName for Union {}
+impl ast::HasVisibility for Union {}
+impl Union {
+    pub fn record_field_list(&self) -> Option<RecordFieldList> { support::child(&self.syntax) }
+    pub fn union_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![union]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct ParenPat {
+pub struct Use {
     pub(crate) syntax: SyntaxNode,
 }
-impl ParenPat {
-    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
-    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
-    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+impl ast::HasAttrs for Use {}
+impl ast::HasDocComments for Use {}
+impl ast::HasVisibility for Use {}
+impl Use {
+    pub fn use_tree(&self) -> Option<UseTree> { support::child(&self.syntax) }
+    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
+    pub fn use_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![use]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct PathPat {
+pub struct UseTree {
     pub(crate) syntax: SyntaxNode,
 }
-impl PathPat {
+impl UseTree {
     pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
+    pub fn rename(&self) -> Option<Rename> { support::child(&self.syntax) }
+    pub fn use_tree_list(&self) -> Option<UseTreeList> { support::child(&self.syntax) }
+    pub fn star_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![*]) }
+    pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct WildcardPat {
+pub struct UseTreeList {
     pub(crate) syntax: SyntaxNode,
 }
-impl WildcardPat {
-    pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
+impl UseTreeList {
+    pub fn use_trees(&self) -> AstChildren<UseTree> { support::children(&self.syntax) }
+    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
+    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RangePat {
+pub struct Variant {
     pub(crate) syntax: SyntaxNode,
 }
-impl RangePat {}
+impl ast::HasAttrs for Variant {}
+impl ast::HasDocComments for Variant {}
+impl ast::HasName for Variant {}
+impl ast::HasVisibility for Variant {}
+impl Variant {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn field_list(&self) -> Option<FieldList> { support::child(&self.syntax) }
+    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
+}
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RecordPat {
+pub struct VariantList {
     pub(crate) syntax: SyntaxNode,
 }
-impl RecordPat {
-    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
-    pub fn record_pat_field_list(&self) -> Option<RecordPatFieldList> {
-        support::child(&self.syntax)
-    }
+impl VariantList {
+    pub fn variants(&self) -> AstChildren<Variant> { support::children(&self.syntax) }
+    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
+    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RefPat {
+pub struct Visibility {
     pub(crate) syntax: SyntaxNode,
 }
-impl RefPat {
-    pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
-    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
-    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
+impl Visibility {
+    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
+    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
+    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+    pub fn in_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![in]) }
+    pub fn pub_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![pub]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct SlicePat {
+pub struct WhereClause {
     pub(crate) syntax: SyntaxNode,
 }
-impl SlicePat {
-    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
-    pub fn pats(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
-    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
+impl WhereClause {
+    pub fn predicates(&self) -> AstChildren<WherePred> { support::children(&self.syntax) }
+    pub fn where_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![where]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct TuplePat {
+pub struct WherePred {
     pub(crate) syntax: SyntaxNode,
 }
-impl TuplePat {
-    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
-    pub fn fields(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
-    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+impl ast::HasTypeBounds for WherePred {}
+impl WherePred {
+    pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
+    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
+    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
+    pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct TupleStructPat {
+pub struct WhileExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl TupleStructPat {
-    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
-    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
-    pub fn fields(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
-    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
+impl ast::HasAttrs for WhileExpr {}
+impl WhileExpr {
+    pub fn while_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![while]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct ConstBlockPat {
+pub struct WildcardPat {
     pub(crate) syntax: SyntaxNode,
 }
-impl ConstBlockPat {
-    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
-    pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
+impl WildcardPat {
+    pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RecordPatFieldList {
+pub struct YeetExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl RecordPatFieldList {
-    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
-    pub fn fields(&self) -> AstChildren<RecordPatField> { support::children(&self.syntax) }
-    pub fn rest_pat(&self) -> Option<RestPat> { support::child(&self.syntax) }
-    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
+impl ast::HasAttrs for YeetExpr {}
+impl YeetExpr {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn do_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![do]) }
+    pub fn yeet_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![yeet]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct RecordPatField {
+pub struct YieldExpr {
     pub(crate) syntax: SyntaxNode,
 }
-impl ast::HasAttrs for RecordPatField {}
-impl RecordPatField {
-    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
-    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
-    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
+impl ast::HasAttrs for YieldExpr {}
+impl YieldExpr {
+    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn yield_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![yield]) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum Type {
-    ArrayType(ArrayType),
-    DynTraitType(DynTraitType),
-    FnPtrType(FnPtrType),
-    ForType(ForType),
-    ImplTraitType(ImplTraitType),
-    InferType(InferType),
-    MacroType(MacroType),
-    NeverType(NeverType),
-    ParenType(ParenType),
-    PathType(PathType),
-    PtrType(PtrType),
-    RefType(RefType),
-    SliceType(SliceType),
-    TupleType(TupleType),
+pub enum Adt {
+    Enum(Enum),
+    Struct(Struct),
+    Union(Union),
 }
+impl ast::HasAttrs for Adt {}
+impl ast::HasDocComments for Adt {}
+impl ast::HasGenericParams for Adt {}
+impl ast::HasName for Adt {}
+impl ast::HasVisibility for Adt {}
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum GenericArg {
-    TypeArg(TypeArg),
-    AssocTypeArg(AssocTypeArg),
-    LifetimeArg(LifetimeArg),
-    ConstArg(ConstArg),
+pub enum AssocItem {
+    Const(Const),
+    Fn(Fn),
+    MacroCall(MacroCall),
+    TypeAlias(TypeAlias),
 }
+impl ast::HasAttrs for AssocItem {}
+impl ast::HasDocComments for AssocItem {}
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum Expr {
     ArrayExpr(ArrayExpr),
     AsmExpr(AsmExpr),
     AwaitExpr(AwaitExpr),
+    BecomeExpr(BecomeExpr),
     BinExpr(BinExpr),
     BlockExpr(BlockExpr),
     BreakExpr(BreakExpr),
@@ -1631,6 +1628,7 @@ pub enum Expr {
     FormatArgsExpr(FormatArgsExpr),
     IfExpr(IfExpr),
     IndexExpr(IndexExpr),
+    LetExpr(LetExpr),
     Literal(Literal),
     LoopExpr(LoopExpr),
     MacroExpr(MacroExpr),
@@ -1644,17 +1642,47 @@ pub enum Expr {
     RecordExpr(RecordExpr),
     RefExpr(RefExpr),
     ReturnExpr(ReturnExpr),
-    BecomeExpr(BecomeExpr),
     TryExpr(TryExpr),
     TupleExpr(TupleExpr),
+    UnderscoreExpr(UnderscoreExpr),
     WhileExpr(WhileExpr),
-    YieldExpr(YieldExpr),
     YeetExpr(YeetExpr),
-    LetExpr(LetExpr),
-    UnderscoreExpr(UnderscoreExpr),
+    YieldExpr(YieldExpr),
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum ExternItem {
+    Fn(Fn),
+    MacroCall(MacroCall),
+    Static(Static),
+    TypeAlias(TypeAlias),
+}
+impl ast::HasAttrs for ExternItem {}
+impl ast::HasDocComments for ExternItem {}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum FieldList {
+    RecordFieldList(RecordFieldList),
+    TupleFieldList(TupleFieldList),
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum GenericArg {
+    AssocTypeArg(AssocTypeArg),
+    ConstArg(ConstArg),
+    LifetimeArg(LifetimeArg),
+    TypeArg(TypeArg),
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum GenericParam {
+    ConstParam(ConstParam),
+    LifetimeParam(LifetimeParam),
+    TypeParam(TypeParam),
+}
+impl ast::HasAttrs for GenericParam {}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum Item {
     Const(Const),
     Enum(Enum),
@@ -1663,8 +1691,8 @@ pub enum Item {
     Fn(Fn),
     Impl(Impl),
     MacroCall(MacroCall),
-    MacroRules(MacroRules),
     MacroDef(MacroDef),
+    MacroRules(MacroRules),
     Module(Module),
     Static(Static),
     Struct(Struct),
@@ -1678,77 +1706,49 @@ impl ast::HasAttrs for Item {}
 impl ast::HasDocComments for Item {}
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum Stmt {
-    ExprStmt(ExprStmt),
-    Item(Item),
-    LetStmt(LetStmt),
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum Pat {
-    IdentPat(IdentPat),
     BoxPat(BoxPat),
-    RestPat(RestPat),
+    ConstBlockPat(ConstBlockPat),
+    IdentPat(IdentPat),
     LiteralPat(LiteralPat),
     MacroPat(MacroPat),
     OrPat(OrPat),
     ParenPat(ParenPat),
     PathPat(PathPat),
-    WildcardPat(WildcardPat),
     RangePat(RangePat),
     RecordPat(RecordPat),
     RefPat(RefPat),
+    RestPat(RestPat),
     SlicePat(SlicePat),
     TuplePat(TuplePat),
     TupleStructPat(TupleStructPat),
-    ConstBlockPat(ConstBlockPat),
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum FieldList {
-    RecordFieldList(RecordFieldList),
-    TupleFieldList(TupleFieldList),
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum Adt {
-    Enum(Enum),
-    Struct(Struct),
-    Union(Union),
+    WildcardPat(WildcardPat),
 }
-impl ast::HasAttrs for Adt {}
-impl ast::HasDocComments for Adt {}
-impl ast::HasGenericParams for Adt {}
-impl ast::HasName for Adt {}
-impl ast::HasVisibility for Adt {}
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum AssocItem {
-    Const(Const),
-    Fn(Fn),
-    MacroCall(MacroCall),
-    TypeAlias(TypeAlias),
-}
-impl ast::HasAttrs for AssocItem {}
-impl ast::HasDocComments for AssocItem {}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum ExternItem {
-    Fn(Fn),
-    MacroCall(MacroCall),
-    Static(Static),
-    TypeAlias(TypeAlias),
+pub enum Stmt {
+    ExprStmt(ExprStmt),
+    Item(Item),
+    LetStmt(LetStmt),
 }
-impl ast::HasAttrs for ExternItem {}
-impl ast::HasDocComments for ExternItem {}
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum GenericParam {
-    ConstParam(ConstParam),
-    LifetimeParam(LifetimeParam),
-    TypeParam(TypeParam),
+pub enum Type {
+    ArrayType(ArrayType),
+    DynTraitType(DynTraitType),
+    FnPtrType(FnPtrType),
+    ForType(ForType),
+    ImplTraitType(ImplTraitType),
+    InferType(InferType),
+    MacroType(MacroType),
+    NeverType(NeverType),
+    ParenType(ParenType),
+    PathType(PathType),
+    PtrType(PtrType),
+    RefType(RefType),
+    SliceType(SliceType),
+    TupleType(TupleType),
 }
-impl ast::HasAttrs for GenericParam {}
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct AnyHasArgList {
@@ -1803,8 +1803,8 @@ pub struct AnyHasVisibility {
     pub(crate) syntax: SyntaxNode,
 }
 impl ast::HasVisibility for AnyHasVisibility {}
-impl AstNode for Name {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == NAME }
+impl AstNode for Abi {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == ABI }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -1814,8 +1814,8 @@ impl AstNode for Name {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for NameRef {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == NAME_REF }
+impl AstNode for ArgList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == ARG_LIST }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -1825,8 +1825,8 @@ impl AstNode for NameRef {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for Lifetime {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == LIFETIME }
+impl AstNode for ArrayExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == ARRAY_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -1836,8 +1836,8 @@ impl AstNode for Lifetime {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for Path {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == PATH }
+impl AstNode for ArrayType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == ARRAY_TYPE }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -1847,8 +1847,8 @@ impl AstNode for Path {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for PathSegment {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_SEGMENT }
+impl AstNode for AsmExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -1858,8 +1858,8 @@ impl AstNode for PathSegment {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for GenericArgList {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == GENERIC_ARG_LIST }
+impl AstNode for AssocItemList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == ASSOC_ITEM_LIST }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -1869,8 +1869,8 @@ impl AstNode for GenericArgList {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for ParamList {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM_LIST }
+impl AstNode for AssocTypeArg {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == ASSOC_TYPE_ARG }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -1880,8 +1880,8 @@ impl AstNode for ParamList {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for RetType {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == RET_TYPE }
+impl AstNode for Attr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == ATTR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -1891,8 +1891,8 @@ impl AstNode for RetType {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for PathType {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_TYPE }
+impl AstNode for AwaitExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == AWAIT_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -1902,8 +1902,8 @@ impl AstNode for PathType {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for TypeArg {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_ARG }
+impl AstNode for BecomeExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == BECOME_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -1913,8 +1913,8 @@ impl AstNode for TypeArg {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for AssocTypeArg {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == ASSOC_TYPE_ARG }
+impl AstNode for BinExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == BIN_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -1924,8 +1924,8 @@ impl AstNode for AssocTypeArg {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for LifetimeArg {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == LIFETIME_ARG }
+impl AstNode for BlockExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == BLOCK_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -1935,8 +1935,8 @@ impl AstNode for LifetimeArg {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for ConstArg {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_ARG }
+impl AstNode for BoxPat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == BOX_PAT }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -1946,8 +1946,8 @@ impl AstNode for ConstArg {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for TypeBoundList {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_BOUND_LIST }
+impl AstNode for BreakExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == BREAK_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -1957,8 +1957,8 @@ impl AstNode for TypeBoundList {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for MacroCall {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_CALL }
+impl AstNode for CallExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == CALL_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -1968,8 +1968,8 @@ impl AstNode for MacroCall {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for Attr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == ATTR }
+impl AstNode for CastExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == CAST_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -1979,8 +1979,8 @@ impl AstNode for Attr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for TokenTree {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == TOKEN_TREE }
+impl AstNode for ClosureExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == CLOSURE_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -1990,8 +1990,8 @@ impl AstNode for TokenTree {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for MacroItems {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_ITEMS }
+impl AstNode for Const {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == CONST }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2001,8 +2001,8 @@ impl AstNode for MacroItems {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for MacroEagerInput {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_EAGER_INPUT }
+impl AstNode for ConstArg {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_ARG }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2012,8 +2012,8 @@ impl AstNode for MacroEagerInput {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for MacroStmts {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_STMTS }
+impl AstNode for ConstBlockPat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_BLOCK_PAT }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2023,8 +2023,8 @@ impl AstNode for MacroStmts {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for SourceFile {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == SOURCE_FILE }
+impl AstNode for ConstParam {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_PARAM }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2034,8 +2034,8 @@ impl AstNode for SourceFile {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for Const {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == CONST }
+impl AstNode for ContinueExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == CONTINUE_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2045,8 +2045,8 @@ impl AstNode for Const {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for Enum {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == ENUM }
+impl AstNode for DynTraitType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == DYN_TRAIT_TYPE }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2056,8 +2056,8 @@ impl AstNode for Enum {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for ExternBlock {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_BLOCK }
+impl AstNode for Enum {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == ENUM }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2067,8 +2067,8 @@ impl AstNode for ExternBlock {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for ExternCrate {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_CRATE }
+impl AstNode for ExprStmt {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_STMT }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2078,8 +2078,8 @@ impl AstNode for ExternCrate {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for Fn {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == FN }
+impl AstNode for ExternBlock {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_BLOCK }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2089,8 +2089,8 @@ impl AstNode for Fn {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for Impl {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == IMPL }
+impl AstNode for ExternCrate {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_CRATE }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2100,8 +2100,8 @@ impl AstNode for Impl {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for MacroRules {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_RULES }
+impl AstNode for ExternItemList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_ITEM_LIST }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2111,8 +2111,8 @@ impl AstNode for MacroRules {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for MacroDef {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_DEF }
+impl AstNode for FieldExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == FIELD_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2122,8 +2122,8 @@ impl AstNode for MacroDef {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for Module {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == MODULE }
+impl AstNode for Fn {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == FN }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2133,8 +2133,8 @@ impl AstNode for Module {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for Static {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == STATIC }
+impl AstNode for FnPtrType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == FN_PTR_TYPE }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2144,8 +2144,8 @@ impl AstNode for Static {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for Struct {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == STRUCT }
+impl AstNode for ForExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2155,8 +2155,8 @@ impl AstNode for Struct {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for Trait {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == TRAIT }
+impl AstNode for ForType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_TYPE }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2166,8 +2166,8 @@ impl AstNode for Trait {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for TraitAlias {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == TRAIT_ALIAS }
+impl AstNode for FormatArgsArg {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == FORMAT_ARGS_ARG }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2177,8 +2177,8 @@ impl AstNode for TraitAlias {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for TypeAlias {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_ALIAS }
+impl AstNode for FormatArgsExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == FORMAT_ARGS_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2188,8 +2188,8 @@ impl AstNode for TypeAlias {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for Union {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == UNION }
+impl AstNode for GenericArgList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == GENERIC_ARG_LIST }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2199,8 +2199,8 @@ impl AstNode for Union {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for Use {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == USE }
+impl AstNode for GenericParamList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == GENERIC_PARAM_LIST }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2210,8 +2210,8 @@ impl AstNode for Use {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for Visibility {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == VISIBILITY }
+impl AstNode for IdentPat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == IDENT_PAT }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2221,8 +2221,8 @@ impl AstNode for Visibility {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for ItemList {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == ITEM_LIST }
+impl AstNode for IfExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == IF_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2232,8 +2232,8 @@ impl AstNode for ItemList {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for Rename {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == RENAME }
+impl AstNode for Impl {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == IMPL }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2243,8 +2243,8 @@ impl AstNode for Rename {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for UseTree {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE }
+impl AstNode for ImplTraitType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == IMPL_TRAIT_TYPE }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2254,8 +2254,8 @@ impl AstNode for UseTree {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for UseTreeList {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE_LIST }
+impl AstNode for IndexExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == INDEX_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2265,8 +2265,8 @@ impl AstNode for UseTreeList {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for Abi {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == ABI }
+impl AstNode for InferType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == INFER_TYPE }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2276,8 +2276,8 @@ impl AstNode for Abi {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for GenericParamList {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == GENERIC_PARAM_LIST }
+impl AstNode for ItemList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == ITEM_LIST }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2287,8 +2287,8 @@ impl AstNode for GenericParamList {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for WhereClause {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == WHERE_CLAUSE }
+impl AstNode for Label {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == LABEL }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2298,8 +2298,8 @@ impl AstNode for WhereClause {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for BlockExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == BLOCK_EXPR }
+impl AstNode for LetElse {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == LET_ELSE }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2309,8 +2309,8 @@ impl AstNode for BlockExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for SelfParam {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == SELF_PARAM }
+impl AstNode for LetExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == LET_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2320,8 +2320,8 @@ impl AstNode for SelfParam {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for Param {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM }
+impl AstNode for LetStmt {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == LET_STMT }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2331,8 +2331,8 @@ impl AstNode for Param {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for RecordFieldList {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD_LIST }
+impl AstNode for Lifetime {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == LIFETIME }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2342,8 +2342,8 @@ impl AstNode for RecordFieldList {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for TupleFieldList {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_FIELD_LIST }
+impl AstNode for LifetimeArg {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == LIFETIME_ARG }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2353,8 +2353,8 @@ impl AstNode for TupleFieldList {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for RecordField {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD }
+impl AstNode for LifetimeParam {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == LIFETIME_PARAM }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2364,8 +2364,8 @@ impl AstNode for RecordField {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for TupleField {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_FIELD }
+impl AstNode for Literal {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == LITERAL }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2375,8 +2375,8 @@ impl AstNode for TupleField {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for VariantList {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == VARIANT_LIST }
+impl AstNode for LiteralPat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == LITERAL_PAT }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2386,8 +2386,8 @@ impl AstNode for VariantList {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for Variant {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == VARIANT }
+impl AstNode for LoopExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == LOOP_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2397,8 +2397,8 @@ impl AstNode for Variant {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for AssocItemList {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == ASSOC_ITEM_LIST }
+impl AstNode for MacroCall {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_CALL }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2408,8 +2408,8 @@ impl AstNode for AssocItemList {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for ExternItemList {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_ITEM_LIST }
+impl AstNode for MacroDef {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_DEF }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2419,8 +2419,8 @@ impl AstNode for ExternItemList {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for ConstParam {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_PARAM }
+impl AstNode for MacroEagerInput {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_EAGER_INPUT }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2430,8 +2430,8 @@ impl AstNode for ConstParam {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for LifetimeParam {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == LIFETIME_PARAM }
+impl AstNode for MacroExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2441,8 +2441,8 @@ impl AstNode for LifetimeParam {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for TypeParam {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_PARAM }
+impl AstNode for MacroItems {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_ITEMS }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2452,8 +2452,8 @@ impl AstNode for TypeParam {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for WherePred {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == WHERE_PRED }
+impl AstNode for MacroPat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_PAT }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2463,8 +2463,8 @@ impl AstNode for WherePred {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for Meta {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == META }
+impl AstNode for MacroRules {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_RULES }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2474,8 +2474,8 @@ impl AstNode for Meta {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for ExprStmt {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_STMT }
+impl AstNode for MacroStmts {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_STMTS }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2485,8 +2485,8 @@ impl AstNode for ExprStmt {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for LetStmt {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == LET_STMT }
+impl AstNode for MacroType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_TYPE }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2496,8 +2496,8 @@ impl AstNode for LetStmt {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for LetElse {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == LET_ELSE }
+impl AstNode for MatchArm {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_ARM }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2507,8 +2507,8 @@ impl AstNode for LetElse {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for ArrayExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == ARRAY_EXPR }
+impl AstNode for MatchArmList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_ARM_LIST }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2518,8 +2518,8 @@ impl AstNode for ArrayExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for AsmExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_EXPR }
+impl AstNode for MatchExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2529,8 +2529,8 @@ impl AstNode for AsmExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for AwaitExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == AWAIT_EXPR }
+impl AstNode for MatchGuard {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_GUARD }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2540,8 +2540,8 @@ impl AstNode for AwaitExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for BinExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == BIN_EXPR }
+impl AstNode for Meta {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == META }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2551,8 +2551,8 @@ impl AstNode for BinExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for BreakExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == BREAK_EXPR }
+impl AstNode for MethodCallExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == METHOD_CALL_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2562,8 +2562,8 @@ impl AstNode for BreakExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for CallExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == CALL_EXPR }
+impl AstNode for Module {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == MODULE }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2573,8 +2573,8 @@ impl AstNode for CallExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for CastExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == CAST_EXPR }
+impl AstNode for Name {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == NAME }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2584,8 +2584,8 @@ impl AstNode for CastExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for ClosureExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == CLOSURE_EXPR }
+impl AstNode for NameRef {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == NAME_REF }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2595,8 +2595,8 @@ impl AstNode for ClosureExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for ContinueExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == CONTINUE_EXPR }
+impl AstNode for NeverType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == NEVER_TYPE }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2606,8 +2606,8 @@ impl AstNode for ContinueExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for FieldExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == FIELD_EXPR }
+impl AstNode for OffsetOfExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == OFFSET_OF_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2617,8 +2617,8 @@ impl AstNode for FieldExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for ForExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_EXPR }
+impl AstNode for OrPat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == OR_PAT }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2628,8 +2628,8 @@ impl AstNode for ForExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for FormatArgsExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == FORMAT_ARGS_EXPR }
+impl AstNode for Param {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2639,8 +2639,8 @@ impl AstNode for FormatArgsExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for IfExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == IF_EXPR }
+impl AstNode for ParamList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM_LIST }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2650,8 +2650,8 @@ impl AstNode for IfExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for IndexExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == INDEX_EXPR }
+impl AstNode for ParenExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2661,8 +2661,8 @@ impl AstNode for IndexExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for Literal {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == LITERAL }
+impl AstNode for ParenPat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_PAT }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2672,8 +2672,8 @@ impl AstNode for Literal {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for LoopExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == LOOP_EXPR }
+impl AstNode for ParenType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_TYPE }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2683,8 +2683,8 @@ impl AstNode for LoopExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for MacroExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_EXPR }
+impl AstNode for Path {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PATH }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2694,8 +2694,8 @@ impl AstNode for MacroExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for MatchExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_EXPR }
+impl AstNode for PathExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2705,8 +2705,8 @@ impl AstNode for MatchExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for MethodCallExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == METHOD_CALL_EXPR }
+impl AstNode for PathPat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_PAT }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2716,8 +2716,8 @@ impl AstNode for MethodCallExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for OffsetOfExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == OFFSET_OF_EXPR }
+impl AstNode for PathSegment {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_SEGMENT }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2727,8 +2727,8 @@ impl AstNode for OffsetOfExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for ParenExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_EXPR }
+impl AstNode for PathType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_TYPE }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2738,8 +2738,8 @@ impl AstNode for ParenExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for PathExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_EXPR }
+impl AstNode for PrefixExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PREFIX_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2749,8 +2749,8 @@ impl AstNode for PathExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for PrefixExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == PREFIX_EXPR }
+impl AstNode for PtrType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == PTR_TYPE }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2771,8 +2771,8 @@ impl AstNode for RangeExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for RecordExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_EXPR }
+impl AstNode for RangePat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RANGE_PAT }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2782,8 +2782,8 @@ impl AstNode for RecordExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for RefExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == REF_EXPR }
+impl AstNode for RecordExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2793,8 +2793,8 @@ impl AstNode for RefExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for ReturnExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == RETURN_EXPR }
+impl AstNode for RecordExprField {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_EXPR_FIELD }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2804,8 +2804,8 @@ impl AstNode for ReturnExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for BecomeExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == BECOME_EXPR }
+impl AstNode for RecordExprFieldList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_EXPR_FIELD_LIST }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2815,8 +2815,8 @@ impl AstNode for BecomeExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for TryExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == TRY_EXPR }
+impl AstNode for RecordField {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2826,8 +2826,8 @@ impl AstNode for TryExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for TupleExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_EXPR }
+impl AstNode for RecordFieldList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD_LIST }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2837,8 +2837,8 @@ impl AstNode for TupleExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for WhileExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == WHILE_EXPR }
+impl AstNode for RecordPat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2848,8 +2848,8 @@ impl AstNode for WhileExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for YieldExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == YIELD_EXPR }
+impl AstNode for RecordPatField {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT_FIELD }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2859,8 +2859,8 @@ impl AstNode for YieldExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for YeetExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == YEET_EXPR }
+impl AstNode for RecordPatFieldList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT_FIELD_LIST }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2870,8 +2870,8 @@ impl AstNode for YeetExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for LetExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == LET_EXPR }
+impl AstNode for RefExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == REF_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2881,8 +2881,8 @@ impl AstNode for LetExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for UnderscoreExpr {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == UNDERSCORE_EXPR }
+impl AstNode for RefPat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == REF_PAT }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2892,8 +2892,8 @@ impl AstNode for UnderscoreExpr {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for FormatArgsArg {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == FORMAT_ARGS_ARG }
+impl AstNode for RefType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == REF_TYPE }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2903,8 +2903,8 @@ impl AstNode for FormatArgsArg {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for StmtList {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == STMT_LIST }
+impl AstNode for Rename {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RENAME }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2914,8 +2914,8 @@ impl AstNode for StmtList {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for Label {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == LABEL }
+impl AstNode for RestPat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == REST_PAT }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2925,8 +2925,8 @@ impl AstNode for Label {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for RecordExprFieldList {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_EXPR_FIELD_LIST }
+impl AstNode for RetType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RET_TYPE }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2936,8 +2936,8 @@ impl AstNode for RecordExprFieldList {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for RecordExprField {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_EXPR_FIELD }
+impl AstNode for ReturnExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == RETURN_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2947,8 +2947,8 @@ impl AstNode for RecordExprField {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for ArgList {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == ARG_LIST }
+impl AstNode for SelfParam {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == SELF_PARAM }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2958,8 +2958,8 @@ impl AstNode for ArgList {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for MatchArmList {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_ARM_LIST }
+impl AstNode for SlicePat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == SLICE_PAT }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2969,8 +2969,8 @@ impl AstNode for MatchArmList {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for MatchArm {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_ARM }
+impl AstNode for SliceType {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == SLICE_TYPE }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2980,8 +2980,8 @@ impl AstNode for MatchArm {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for MatchGuard {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_GUARD }
+impl AstNode for SourceFile {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == SOURCE_FILE }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -2991,8 +2991,8 @@ impl AstNode for MatchGuard {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for ArrayType {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == ARRAY_TYPE }
+impl AstNode for Static {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == STATIC }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3002,8 +3002,8 @@ impl AstNode for ArrayType {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for DynTraitType {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == DYN_TRAIT_TYPE }
+impl AstNode for StmtList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == STMT_LIST }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3013,8 +3013,8 @@ impl AstNode for DynTraitType {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for FnPtrType {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == FN_PTR_TYPE }
+impl AstNode for Struct {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == STRUCT }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3024,8 +3024,8 @@ impl AstNode for FnPtrType {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for ForType {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_TYPE }
+impl AstNode for TokenTree {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TOKEN_TREE }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3035,8 +3035,8 @@ impl AstNode for ForType {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for ImplTraitType {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == IMPL_TRAIT_TYPE }
+impl AstNode for Trait {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TRAIT }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3046,8 +3046,8 @@ impl AstNode for ImplTraitType {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for InferType {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == INFER_TYPE }
+impl AstNode for TraitAlias {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TRAIT_ALIAS }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3057,8 +3057,8 @@ impl AstNode for InferType {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for MacroType {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_TYPE }
+impl AstNode for TryExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TRY_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3068,8 +3068,8 @@ impl AstNode for MacroType {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for NeverType {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == NEVER_TYPE }
+impl AstNode for TupleExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3079,8 +3079,8 @@ impl AstNode for NeverType {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for ParenType {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_TYPE }
+impl AstNode for TupleField {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_FIELD }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3090,8 +3090,8 @@ impl AstNode for ParenType {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for PtrType {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == PTR_TYPE }
+impl AstNode for TupleFieldList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_FIELD_LIST }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3101,8 +3101,8 @@ impl AstNode for PtrType {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for RefType {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == REF_TYPE }
+impl AstNode for TuplePat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_PAT }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3112,8 +3112,8 @@ impl AstNode for RefType {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for SliceType {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == SLICE_TYPE }
+impl AstNode for TupleStructPat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_STRUCT_PAT }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3134,8 +3134,8 @@ impl AstNode for TupleType {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for TypeBound {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_BOUND }
+impl AstNode for TypeAlias {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_ALIAS }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3145,8 +3145,8 @@ impl AstNode for TypeBound {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for IdentPat {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == IDENT_PAT }
+impl AstNode for TypeArg {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_ARG }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3156,8 +3156,8 @@ impl AstNode for IdentPat {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for BoxPat {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == BOX_PAT }
+impl AstNode for TypeBound {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_BOUND }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3167,8 +3167,8 @@ impl AstNode for BoxPat {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for RestPat {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == REST_PAT }
+impl AstNode for TypeBoundList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_BOUND_LIST }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3178,8 +3178,8 @@ impl AstNode for RestPat {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for LiteralPat {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == LITERAL_PAT }
+impl AstNode for TypeParam {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_PARAM }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3189,8 +3189,8 @@ impl AstNode for LiteralPat {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for MacroPat {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_PAT }
+impl AstNode for UnderscoreExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == UNDERSCORE_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3200,8 +3200,8 @@ impl AstNode for MacroPat {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for OrPat {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == OR_PAT }
+impl AstNode for Union {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == UNION }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3211,8 +3211,8 @@ impl AstNode for OrPat {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for ParenPat {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_PAT }
+impl AstNode for Use {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == USE }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3222,8 +3222,8 @@ impl AstNode for ParenPat {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for PathPat {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_PAT }
+impl AstNode for UseTree {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3233,8 +3233,8 @@ impl AstNode for PathPat {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for WildcardPat {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == WILDCARD_PAT }
+impl AstNode for UseTreeList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE_LIST }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3244,8 +3244,8 @@ impl AstNode for WildcardPat {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for RangePat {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == RANGE_PAT }
+impl AstNode for Variant {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == VARIANT }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3255,8 +3255,8 @@ impl AstNode for RangePat {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for RecordPat {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT }
+impl AstNode for VariantList {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == VARIANT_LIST }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3266,8 +3266,8 @@ impl AstNode for RecordPat {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for RefPat {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == REF_PAT }
+impl AstNode for Visibility {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == VISIBILITY }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3277,8 +3277,8 @@ impl AstNode for RefPat {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for SlicePat {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == SLICE_PAT }
+impl AstNode for WhereClause {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == WHERE_CLAUSE }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3288,8 +3288,8 @@ impl AstNode for SlicePat {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for TuplePat {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_PAT }
+impl AstNode for WherePred {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == WHERE_PRED }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3299,8 +3299,8 @@ impl AstNode for TuplePat {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for TupleStructPat {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_STRUCT_PAT }
+impl AstNode for WhileExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == WHILE_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3310,8 +3310,8 @@ impl AstNode for TupleStructPat {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for ConstBlockPat {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_BLOCK_PAT }
+impl AstNode for WildcardPat {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == WILDCARD_PAT }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3321,8 +3321,8 @@ impl AstNode for ConstBlockPat {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for RecordPatFieldList {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT_FIELD_LIST }
+impl AstNode for YeetExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == YEET_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3332,8 +3332,8 @@ impl AstNode for RecordPatFieldList {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl AstNode for RecordPatField {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT_FIELD }
+impl AstNode for YieldExpr {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == YIELD_EXPR }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -3343,139 +3343,64 @@ impl AstNode for RecordPatField {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl From<ArrayType> for Type {
-    fn from(node: ArrayType) -> Type { Type::ArrayType(node) }
-}
-impl From<DynTraitType> for Type {
-    fn from(node: DynTraitType) -> Type { Type::DynTraitType(node) }
-}
-impl From<FnPtrType> for Type {
-    fn from(node: FnPtrType) -> Type { Type::FnPtrType(node) }
-}
-impl From<ForType> for Type {
-    fn from(node: ForType) -> Type { Type::ForType(node) }
-}
-impl From<ImplTraitType> for Type {
-    fn from(node: ImplTraitType) -> Type { Type::ImplTraitType(node) }
-}
-impl From<InferType> for Type {
-    fn from(node: InferType) -> Type { Type::InferType(node) }
-}
-impl From<MacroType> for Type {
-    fn from(node: MacroType) -> Type { Type::MacroType(node) }
-}
-impl From<NeverType> for Type {
-    fn from(node: NeverType) -> Type { Type::NeverType(node) }
-}
-impl From<ParenType> for Type {
-    fn from(node: ParenType) -> Type { Type::ParenType(node) }
-}
-impl From<PathType> for Type {
-    fn from(node: PathType) -> Type { Type::PathType(node) }
-}
-impl From<PtrType> for Type {
-    fn from(node: PtrType) -> Type { Type::PtrType(node) }
-}
-impl From<RefType> for Type {
-    fn from(node: RefType) -> Type { Type::RefType(node) }
+impl From<Enum> for Adt {
+    fn from(node: Enum) -> Adt { Adt::Enum(node) }
 }
-impl From<SliceType> for Type {
-    fn from(node: SliceType) -> Type { Type::SliceType(node) }
+impl From<Struct> for Adt {
+    fn from(node: Struct) -> Adt { Adt::Struct(node) }
 }
-impl From<TupleType> for Type {
-    fn from(node: TupleType) -> Type { Type::TupleType(node) }
+impl From<Union> for Adt {
+    fn from(node: Union) -> Adt { Adt::Union(node) }
 }
-impl AstNode for Type {
-    fn can_cast(kind: SyntaxKind) -> bool {
-        matches!(
-            kind,
-            ARRAY_TYPE
-                | DYN_TRAIT_TYPE
-                | FN_PTR_TYPE
-                | FOR_TYPE
-                | IMPL_TRAIT_TYPE
-                | INFER_TYPE
-                | MACRO_TYPE
-                | NEVER_TYPE
-                | PAREN_TYPE
-                | PATH_TYPE
-                | PTR_TYPE
-                | REF_TYPE
-                | SLICE_TYPE
-                | TUPLE_TYPE
-        )
-    }
+impl AstNode for Adt {
+    fn can_cast(kind: SyntaxKind) -> bool { matches!(kind, ENUM | STRUCT | UNION) }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         let res = match syntax.kind() {
-            ARRAY_TYPE => Type::ArrayType(ArrayType { syntax }),
-            DYN_TRAIT_TYPE => Type::DynTraitType(DynTraitType { syntax }),
-            FN_PTR_TYPE => Type::FnPtrType(FnPtrType { syntax }),
-            FOR_TYPE => Type::ForType(ForType { syntax }),
-            IMPL_TRAIT_TYPE => Type::ImplTraitType(ImplTraitType { syntax }),
-            INFER_TYPE => Type::InferType(InferType { syntax }),
-            MACRO_TYPE => Type::MacroType(MacroType { syntax }),
-            NEVER_TYPE => Type::NeverType(NeverType { syntax }),
-            PAREN_TYPE => Type::ParenType(ParenType { syntax }),
-            PATH_TYPE => Type::PathType(PathType { syntax }),
-            PTR_TYPE => Type::PtrType(PtrType { syntax }),
-            REF_TYPE => Type::RefType(RefType { syntax }),
-            SLICE_TYPE => Type::SliceType(SliceType { syntax }),
-            TUPLE_TYPE => Type::TupleType(TupleType { syntax }),
+            ENUM => Adt::Enum(Enum { syntax }),
+            STRUCT => Adt::Struct(Struct { syntax }),
+            UNION => Adt::Union(Union { syntax }),
             _ => return None,
         };
         Some(res)
     }
     fn syntax(&self) -> &SyntaxNode {
         match self {
-            Type::ArrayType(it) => &it.syntax,
-            Type::DynTraitType(it) => &it.syntax,
-            Type::FnPtrType(it) => &it.syntax,
-            Type::ForType(it) => &it.syntax,
-            Type::ImplTraitType(it) => &it.syntax,
-            Type::InferType(it) => &it.syntax,
-            Type::MacroType(it) => &it.syntax,
-            Type::NeverType(it) => &it.syntax,
-            Type::ParenType(it) => &it.syntax,
-            Type::PathType(it) => &it.syntax,
-            Type::PtrType(it) => &it.syntax,
-            Type::RefType(it) => &it.syntax,
-            Type::SliceType(it) => &it.syntax,
-            Type::TupleType(it) => &it.syntax,
+            Adt::Enum(it) => &it.syntax,
+            Adt::Struct(it) => &it.syntax,
+            Adt::Union(it) => &it.syntax,
         }
     }
 }
-impl From<TypeArg> for GenericArg {
-    fn from(node: TypeArg) -> GenericArg { GenericArg::TypeArg(node) }
+impl From<Const> for AssocItem {
+    fn from(node: Const) -> AssocItem { AssocItem::Const(node) }
 }
-impl From<AssocTypeArg> for GenericArg {
-    fn from(node: AssocTypeArg) -> GenericArg { GenericArg::AssocTypeArg(node) }
+impl From<Fn> for AssocItem {
+    fn from(node: Fn) -> AssocItem { AssocItem::Fn(node) }
 }
-impl From<LifetimeArg> for GenericArg {
-    fn from(node: LifetimeArg) -> GenericArg { GenericArg::LifetimeArg(node) }
+impl From<MacroCall> for AssocItem {
+    fn from(node: MacroCall) -> AssocItem { AssocItem::MacroCall(node) }
 }
-impl From<ConstArg> for GenericArg {
-    fn from(node: ConstArg) -> GenericArg { GenericArg::ConstArg(node) }
+impl From<TypeAlias> for AssocItem {
+    fn from(node: TypeAlias) -> AssocItem { AssocItem::TypeAlias(node) }
 }
-impl AstNode for GenericArg {
-    fn can_cast(kind: SyntaxKind) -> bool {
-        matches!(kind, TYPE_ARG | ASSOC_TYPE_ARG | LIFETIME_ARG | CONST_ARG)
-    }
+impl AstNode for AssocItem {
+    fn can_cast(kind: SyntaxKind) -> bool { matches!(kind, CONST | FN | MACRO_CALL | TYPE_ALIAS) }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         let res = match syntax.kind() {
-            TYPE_ARG => GenericArg::TypeArg(TypeArg { syntax }),
-            ASSOC_TYPE_ARG => GenericArg::AssocTypeArg(AssocTypeArg { syntax }),
-            LIFETIME_ARG => GenericArg::LifetimeArg(LifetimeArg { syntax }),
-            CONST_ARG => GenericArg::ConstArg(ConstArg { syntax }),
+            CONST => AssocItem::Const(Const { syntax }),
+            FN => AssocItem::Fn(Fn { syntax }),
+            MACRO_CALL => AssocItem::MacroCall(MacroCall { syntax }),
+            TYPE_ALIAS => AssocItem::TypeAlias(TypeAlias { syntax }),
             _ => return None,
         };
         Some(res)
     }
     fn syntax(&self) -> &SyntaxNode {
         match self {
-            GenericArg::TypeArg(it) => &it.syntax,
-            GenericArg::AssocTypeArg(it) => &it.syntax,
-            GenericArg::LifetimeArg(it) => &it.syntax,
-            GenericArg::ConstArg(it) => &it.syntax,
+            AssocItem::Const(it) => &it.syntax,
+            AssocItem::Fn(it) => &it.syntax,
+            AssocItem::MacroCall(it) => &it.syntax,
+            AssocItem::TypeAlias(it) => &it.syntax,
         }
     }
 }
@@ -3488,6 +3413,9 @@ impl From<AsmExpr> for Expr {
 impl From<AwaitExpr> for Expr {
     fn from(node: AwaitExpr) -> Expr { Expr::AwaitExpr(node) }
 }
+impl From<BecomeExpr> for Expr {
+    fn from(node: BecomeExpr) -> Expr { Expr::BecomeExpr(node) }
+}
 impl From<BinExpr> for Expr {
     fn from(node: BinExpr) -> Expr { Expr::BinExpr(node) }
 }
@@ -3524,6 +3452,9 @@ impl From<IfExpr> for Expr {
 impl From<IndexExpr> for Expr {
     fn from(node: IndexExpr) -> Expr { Expr::IndexExpr(node) }
 }
+impl From<LetExpr> for Expr {
+    fn from(node: LetExpr) -> Expr { Expr::LetExpr(node) }
+}
 impl From<Literal> for Expr {
     fn from(node: Literal) -> Expr { Expr::Literal(node) }
 }
@@ -3563,29 +3494,23 @@ impl From<RefExpr> for Expr {
 impl From<ReturnExpr> for Expr {
     fn from(node: ReturnExpr) -> Expr { Expr::ReturnExpr(node) }
 }
-impl From<BecomeExpr> for Expr {
-    fn from(node: BecomeExpr) -> Expr { Expr::BecomeExpr(node) }
-}
 impl From<TryExpr> for Expr {
     fn from(node: TryExpr) -> Expr { Expr::TryExpr(node) }
 }
 impl From<TupleExpr> for Expr {
     fn from(node: TupleExpr) -> Expr { Expr::TupleExpr(node) }
 }
+impl From<UnderscoreExpr> for Expr {
+    fn from(node: UnderscoreExpr) -> Expr { Expr::UnderscoreExpr(node) }
+}
 impl From<WhileExpr> for Expr {
     fn from(node: WhileExpr) -> Expr { Expr::WhileExpr(node) }
 }
-impl From<YieldExpr> for Expr {
-    fn from(node: YieldExpr) -> Expr { Expr::YieldExpr(node) }
-}
 impl From<YeetExpr> for Expr {
     fn from(node: YeetExpr) -> Expr { Expr::YeetExpr(node) }
 }
-impl From<LetExpr> for Expr {
-    fn from(node: LetExpr) -> Expr { Expr::LetExpr(node) }
-}
-impl From<UnderscoreExpr> for Expr {
-    fn from(node: UnderscoreExpr) -> Expr { Expr::UnderscoreExpr(node) }
+impl From<YieldExpr> for Expr {
+    fn from(node: YieldExpr) -> Expr { Expr::YieldExpr(node) }
 }
 impl AstNode for Expr {
     fn can_cast(kind: SyntaxKind) -> bool {
@@ -3594,6 +3519,7 @@ impl AstNode for Expr {
             ARRAY_EXPR
                 | ASM_EXPR
                 | AWAIT_EXPR
+                | BECOME_EXPR
                 | BIN_EXPR
                 | BLOCK_EXPR
                 | BREAK_EXPR
@@ -3606,6 +3532,7 @@ impl AstNode for Expr {
                 | FORMAT_ARGS_EXPR
                 | IF_EXPR
                 | INDEX_EXPR
+                | LET_EXPR
                 | LITERAL
                 | LOOP_EXPR
                 | MACRO_EXPR
@@ -3619,14 +3546,12 @@ impl AstNode for Expr {
                 | RECORD_EXPR
                 | REF_EXPR
                 | RETURN_EXPR
-                | BECOME_EXPR
                 | TRY_EXPR
                 | TUPLE_EXPR
+                | UNDERSCORE_EXPR
                 | WHILE_EXPR
-                | YIELD_EXPR
                 | YEET_EXPR
-                | LET_EXPR
-                | UNDERSCORE_EXPR
+                | YIELD_EXPR
         )
     }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3634,6 +3559,7 @@ impl AstNode for Expr {
             ARRAY_EXPR => Expr::ArrayExpr(ArrayExpr { syntax }),
             ASM_EXPR => Expr::AsmExpr(AsmExpr { syntax }),
             AWAIT_EXPR => Expr::AwaitExpr(AwaitExpr { syntax }),
+            BECOME_EXPR => Expr::BecomeExpr(BecomeExpr { syntax }),
             BIN_EXPR => Expr::BinExpr(BinExpr { syntax }),
             BLOCK_EXPR => Expr::BlockExpr(BlockExpr { syntax }),
             BREAK_EXPR => Expr::BreakExpr(BreakExpr { syntax }),
@@ -3646,6 +3572,7 @@ impl AstNode for Expr {
             FORMAT_ARGS_EXPR => Expr::FormatArgsExpr(FormatArgsExpr { syntax }),
             IF_EXPR => Expr::IfExpr(IfExpr { syntax }),
             INDEX_EXPR => Expr::IndexExpr(IndexExpr { syntax }),
+            LET_EXPR => Expr::LetExpr(LetExpr { syntax }),
             LITERAL => Expr::Literal(Literal { syntax }),
             LOOP_EXPR => Expr::LoopExpr(LoopExpr { syntax }),
             MACRO_EXPR => Expr::MacroExpr(MacroExpr { syntax }),
@@ -3659,14 +3586,12 @@ impl AstNode for Expr {
             RECORD_EXPR => Expr::RecordExpr(RecordExpr { syntax }),
             REF_EXPR => Expr::RefExpr(RefExpr { syntax }),
             RETURN_EXPR => Expr::ReturnExpr(ReturnExpr { syntax }),
-            BECOME_EXPR => Expr::BecomeExpr(BecomeExpr { syntax }),
             TRY_EXPR => Expr::TryExpr(TryExpr { syntax }),
             TUPLE_EXPR => Expr::TupleExpr(TupleExpr { syntax }),
+            UNDERSCORE_EXPR => Expr::UnderscoreExpr(UnderscoreExpr { syntax }),
             WHILE_EXPR => Expr::WhileExpr(WhileExpr { syntax }),
-            YIELD_EXPR => Expr::YieldExpr(YieldExpr { syntax }),
             YEET_EXPR => Expr::YeetExpr(YeetExpr { syntax }),
-            LET_EXPR => Expr::LetExpr(LetExpr { syntax }),
-            UNDERSCORE_EXPR => Expr::UnderscoreExpr(UnderscoreExpr { syntax }),
+            YIELD_EXPR => Expr::YieldExpr(YieldExpr { syntax }),
             _ => return None,
         };
         Some(res)
@@ -3676,6 +3601,7 @@ impl AstNode for Expr {
             Expr::ArrayExpr(it) => &it.syntax,
             Expr::AsmExpr(it) => &it.syntax,
             Expr::AwaitExpr(it) => &it.syntax,
+            Expr::BecomeExpr(it) => &it.syntax,
             Expr::BinExpr(it) => &it.syntax,
             Expr::BlockExpr(it) => &it.syntax,
             Expr::BreakExpr(it) => &it.syntax,
@@ -3688,6 +3614,7 @@ impl AstNode for Expr {
             Expr::FormatArgsExpr(it) => &it.syntax,
             Expr::IfExpr(it) => &it.syntax,
             Expr::IndexExpr(it) => &it.syntax,
+            Expr::LetExpr(it) => &it.syntax,
             Expr::Literal(it) => &it.syntax,
             Expr::LoopExpr(it) => &it.syntax,
             Expr::MacroExpr(it) => &it.syntax,
@@ -3701,14 +3628,133 @@ impl AstNode for Expr {
             Expr::RecordExpr(it) => &it.syntax,
             Expr::RefExpr(it) => &it.syntax,
             Expr::ReturnExpr(it) => &it.syntax,
-            Expr::BecomeExpr(it) => &it.syntax,
             Expr::TryExpr(it) => &it.syntax,
             Expr::TupleExpr(it) => &it.syntax,
+            Expr::UnderscoreExpr(it) => &it.syntax,
             Expr::WhileExpr(it) => &it.syntax,
-            Expr::YieldExpr(it) => &it.syntax,
             Expr::YeetExpr(it) => &it.syntax,
-            Expr::LetExpr(it) => &it.syntax,
-            Expr::UnderscoreExpr(it) => &it.syntax,
+            Expr::YieldExpr(it) => &it.syntax,
+        }
+    }
+}
+impl From<Fn> for ExternItem {
+    fn from(node: Fn) -> ExternItem { ExternItem::Fn(node) }
+}
+impl From<MacroCall> for ExternItem {
+    fn from(node: MacroCall) -> ExternItem { ExternItem::MacroCall(node) }
+}
+impl From<Static> for ExternItem {
+    fn from(node: Static) -> ExternItem { ExternItem::Static(node) }
+}
+impl From<TypeAlias> for ExternItem {
+    fn from(node: TypeAlias) -> ExternItem { ExternItem::TypeAlias(node) }
+}
+impl AstNode for ExternItem {
+    fn can_cast(kind: SyntaxKind) -> bool { matches!(kind, FN | MACRO_CALL | STATIC | TYPE_ALIAS) }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        let res = match syntax.kind() {
+            FN => ExternItem::Fn(Fn { syntax }),
+            MACRO_CALL => ExternItem::MacroCall(MacroCall { syntax }),
+            STATIC => ExternItem::Static(Static { syntax }),
+            TYPE_ALIAS => ExternItem::TypeAlias(TypeAlias { syntax }),
+            _ => return None,
+        };
+        Some(res)
+    }
+    fn syntax(&self) -> &SyntaxNode {
+        match self {
+            ExternItem::Fn(it) => &it.syntax,
+            ExternItem::MacroCall(it) => &it.syntax,
+            ExternItem::Static(it) => &it.syntax,
+            ExternItem::TypeAlias(it) => &it.syntax,
+        }
+    }
+}
+impl From<RecordFieldList> for FieldList {
+    fn from(node: RecordFieldList) -> FieldList { FieldList::RecordFieldList(node) }
+}
+impl From<TupleFieldList> for FieldList {
+    fn from(node: TupleFieldList) -> FieldList { FieldList::TupleFieldList(node) }
+}
+impl AstNode for FieldList {
+    fn can_cast(kind: SyntaxKind) -> bool { matches!(kind, RECORD_FIELD_LIST | TUPLE_FIELD_LIST) }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        let res = match syntax.kind() {
+            RECORD_FIELD_LIST => FieldList::RecordFieldList(RecordFieldList { syntax }),
+            TUPLE_FIELD_LIST => FieldList::TupleFieldList(TupleFieldList { syntax }),
+            _ => return None,
+        };
+        Some(res)
+    }
+    fn syntax(&self) -> &SyntaxNode {
+        match self {
+            FieldList::RecordFieldList(it) => &it.syntax,
+            FieldList::TupleFieldList(it) => &it.syntax,
+        }
+    }
+}
+impl From<AssocTypeArg> for GenericArg {
+    fn from(node: AssocTypeArg) -> GenericArg { GenericArg::AssocTypeArg(node) }
+}
+impl From<ConstArg> for GenericArg {
+    fn from(node: ConstArg) -> GenericArg { GenericArg::ConstArg(node) }
+}
+impl From<LifetimeArg> for GenericArg {
+    fn from(node: LifetimeArg) -> GenericArg { GenericArg::LifetimeArg(node) }
+}
+impl From<TypeArg> for GenericArg {
+    fn from(node: TypeArg) -> GenericArg { GenericArg::TypeArg(node) }
+}
+impl AstNode for GenericArg {
+    fn can_cast(kind: SyntaxKind) -> bool {
+        matches!(kind, ASSOC_TYPE_ARG | CONST_ARG | LIFETIME_ARG | TYPE_ARG)
+    }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        let res = match syntax.kind() {
+            ASSOC_TYPE_ARG => GenericArg::AssocTypeArg(AssocTypeArg { syntax }),
+            CONST_ARG => GenericArg::ConstArg(ConstArg { syntax }),
+            LIFETIME_ARG => GenericArg::LifetimeArg(LifetimeArg { syntax }),
+            TYPE_ARG => GenericArg::TypeArg(TypeArg { syntax }),
+            _ => return None,
+        };
+        Some(res)
+    }
+    fn syntax(&self) -> &SyntaxNode {
+        match self {
+            GenericArg::AssocTypeArg(it) => &it.syntax,
+            GenericArg::ConstArg(it) => &it.syntax,
+            GenericArg::LifetimeArg(it) => &it.syntax,
+            GenericArg::TypeArg(it) => &it.syntax,
+        }
+    }
+}
+impl From<ConstParam> for GenericParam {
+    fn from(node: ConstParam) -> GenericParam { GenericParam::ConstParam(node) }
+}
+impl From<LifetimeParam> for GenericParam {
+    fn from(node: LifetimeParam) -> GenericParam { GenericParam::LifetimeParam(node) }
+}
+impl From<TypeParam> for GenericParam {
+    fn from(node: TypeParam) -> GenericParam { GenericParam::TypeParam(node) }
+}
+impl AstNode for GenericParam {
+    fn can_cast(kind: SyntaxKind) -> bool {
+        matches!(kind, CONST_PARAM | LIFETIME_PARAM | TYPE_PARAM)
+    }
+    fn cast(syntax: SyntaxNode) -> Option<Self> {
+        let res = match syntax.kind() {
+            CONST_PARAM => GenericParam::ConstParam(ConstParam { syntax }),
+            LIFETIME_PARAM => GenericParam::LifetimeParam(LifetimeParam { syntax }),
+            TYPE_PARAM => GenericParam::TypeParam(TypeParam { syntax }),
+            _ => return None,
+        };
+        Some(res)
+    }
+    fn syntax(&self) -> &SyntaxNode {
+        match self {
+            GenericParam::ConstParam(it) => &it.syntax,
+            GenericParam::LifetimeParam(it) => &it.syntax,
+            GenericParam::TypeParam(it) => &it.syntax,
         }
     }
 }
@@ -3733,12 +3779,12 @@ impl From<Impl> for Item {
 impl From<MacroCall> for Item {
     fn from(node: MacroCall) -> Item { Item::MacroCall(node) }
 }
-impl From<MacroRules> for Item {
-    fn from(node: MacroRules) -> Item { Item::MacroRules(node) }
-}
 impl From<MacroDef> for Item {
     fn from(node: MacroDef) -> Item { Item::MacroDef(node) }
 }
+impl From<MacroRules> for Item {
+    fn from(node: MacroRules) -> Item { Item::MacroRules(node) }
+}
 impl From<Module> for Item {
     fn from(node: Module) -> Item { Item::Module(node) }
 }
@@ -3774,8 +3820,8 @@ impl AstNode for Item {
                 | FN
                 | IMPL
                 | MACRO_CALL
-                | MACRO_RULES
                 | MACRO_DEF
+                | MACRO_RULES
                 | MODULE
                 | STATIC
                 | STRUCT
@@ -3795,8 +3841,8 @@ impl AstNode for Item {
             FN => Item::Fn(Fn { syntax }),
             IMPL => Item::Impl(Impl { syntax }),
             MACRO_CALL => Item::MacroCall(MacroCall { syntax }),
-            MACRO_RULES => Item::MacroRules(MacroRules { syntax }),
             MACRO_DEF => Item::MacroDef(MacroDef { syntax }),
+            MACRO_RULES => Item::MacroRules(MacroRules { syntax }),
             MODULE => Item::Module(Module { syntax }),
             STATIC => Item::Static(Static { syntax }),
             STRUCT => Item::Struct(Struct { syntax }),
@@ -3818,8 +3864,8 @@ impl AstNode for Item {
             Item::Fn(it) => &it.syntax,
             Item::Impl(it) => &it.syntax,
             Item::MacroCall(it) => &it.syntax,
-            Item::MacroRules(it) => &it.syntax,
             Item::MacroDef(it) => &it.syntax,
+            Item::MacroRules(it) => &it.syntax,
             Item::Module(it) => &it.syntax,
             Item::Static(it) => &it.syntax,
             Item::Struct(it) => &it.syntax,
@@ -3831,24 +3877,15 @@ impl AstNode for Item {
         }
     }
 }
-impl From<ExprStmt> for Stmt {
-    fn from(node: ExprStmt) -> Stmt { Stmt::ExprStmt(node) }
-}
-impl From<Item> for Stmt {
-    fn from(node: Item) -> Stmt { Stmt::Item(node) }
+impl From<BoxPat> for Pat {
+    fn from(node: BoxPat) -> Pat { Pat::BoxPat(node) }
 }
-impl From<LetStmt> for Stmt {
-    fn from(node: LetStmt) -> Stmt { Stmt::LetStmt(node) }
+impl From<ConstBlockPat> for Pat {
+    fn from(node: ConstBlockPat) -> Pat { Pat::ConstBlockPat(node) }
 }
 impl From<IdentPat> for Pat {
     fn from(node: IdentPat) -> Pat { Pat::IdentPat(node) }
 }
-impl From<BoxPat> for Pat {
-    fn from(node: BoxPat) -> Pat { Pat::BoxPat(node) }
-}
-impl From<RestPat> for Pat {
-    fn from(node: RestPat) -> Pat { Pat::RestPat(node) }
-}
 impl From<LiteralPat> for Pat {
     fn from(node: LiteralPat) -> Pat { Pat::LiteralPat(node) }
 }
@@ -3864,9 +3901,6 @@ impl From<ParenPat> for Pat {
 impl From<PathPat> for Pat {
     fn from(node: PathPat) -> Pat { Pat::PathPat(node) }
 }
-impl From<WildcardPat> for Pat {
-    fn from(node: WildcardPat) -> Pat { Pat::WildcardPat(node) }
-}
 impl From<RangePat> for Pat {
     fn from(node: RangePat) -> Pat { Pat::RangePat(node) }
 }
@@ -3876,6 +3910,9 @@ impl From<RecordPat> for Pat {
 impl From<RefPat> for Pat {
     fn from(node: RefPat) -> Pat { Pat::RefPat(node) }
 }
+impl From<RestPat> for Pat {
+    fn from(node: RestPat) -> Pat { Pat::RestPat(node) }
+}
 impl From<SlicePat> for Pat {
     fn from(node: SlicePat) -> Pat { Pat::SlicePat(node) }
 }
@@ -3885,218 +3922,181 @@ impl From<TuplePat> for Pat {
 impl From<TupleStructPat> for Pat {
     fn from(node: TupleStructPat) -> Pat { Pat::TupleStructPat(node) }
 }
-impl From<ConstBlockPat> for Pat {
-    fn from(node: ConstBlockPat) -> Pat { Pat::ConstBlockPat(node) }
+impl From<WildcardPat> for Pat {
+    fn from(node: WildcardPat) -> Pat { Pat::WildcardPat(node) }
 }
 impl AstNode for Pat {
     fn can_cast(kind: SyntaxKind) -> bool {
         matches!(
             kind,
-            IDENT_PAT
-                | BOX_PAT
-                | REST_PAT
+            BOX_PAT
+                | CONST_BLOCK_PAT
+                | IDENT_PAT
                 | LITERAL_PAT
                 | MACRO_PAT
                 | OR_PAT
                 | PAREN_PAT
                 | PATH_PAT
-                | WILDCARD_PAT
                 | RANGE_PAT
                 | RECORD_PAT
                 | REF_PAT
+                | REST_PAT
                 | SLICE_PAT
                 | TUPLE_PAT
                 | TUPLE_STRUCT_PAT
-                | CONST_BLOCK_PAT
+                | WILDCARD_PAT
         )
     }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         let res = match syntax.kind() {
-            IDENT_PAT => Pat::IdentPat(IdentPat { syntax }),
             BOX_PAT => Pat::BoxPat(BoxPat { syntax }),
-            REST_PAT => Pat::RestPat(RestPat { syntax }),
+            CONST_BLOCK_PAT => Pat::ConstBlockPat(ConstBlockPat { syntax }),
+            IDENT_PAT => Pat::IdentPat(IdentPat { syntax }),
             LITERAL_PAT => Pat::LiteralPat(LiteralPat { syntax }),
             MACRO_PAT => Pat::MacroPat(MacroPat { syntax }),
             OR_PAT => Pat::OrPat(OrPat { syntax }),
             PAREN_PAT => Pat::ParenPat(ParenPat { syntax }),
             PATH_PAT => Pat::PathPat(PathPat { syntax }),
-            WILDCARD_PAT => Pat::WildcardPat(WildcardPat { syntax }),
             RANGE_PAT => Pat::RangePat(RangePat { syntax }),
             RECORD_PAT => Pat::RecordPat(RecordPat { syntax }),
             REF_PAT => Pat::RefPat(RefPat { syntax }),
+            REST_PAT => Pat::RestPat(RestPat { syntax }),
             SLICE_PAT => Pat::SlicePat(SlicePat { syntax }),
             TUPLE_PAT => Pat::TuplePat(TuplePat { syntax }),
             TUPLE_STRUCT_PAT => Pat::TupleStructPat(TupleStructPat { syntax }),
-            CONST_BLOCK_PAT => Pat::ConstBlockPat(ConstBlockPat { syntax }),
+            WILDCARD_PAT => Pat::WildcardPat(WildcardPat { syntax }),
             _ => return None,
         };
         Some(res)
     }
     fn syntax(&self) -> &SyntaxNode {
         match self {
-            Pat::IdentPat(it) => &it.syntax,
             Pat::BoxPat(it) => &it.syntax,
-            Pat::RestPat(it) => &it.syntax,
+            Pat::ConstBlockPat(it) => &it.syntax,
+            Pat::IdentPat(it) => &it.syntax,
             Pat::LiteralPat(it) => &it.syntax,
             Pat::MacroPat(it) => &it.syntax,
             Pat::OrPat(it) => &it.syntax,
             Pat::ParenPat(it) => &it.syntax,
             Pat::PathPat(it) => &it.syntax,
-            Pat::WildcardPat(it) => &it.syntax,
             Pat::RangePat(it) => &it.syntax,
             Pat::RecordPat(it) => &it.syntax,
             Pat::RefPat(it) => &it.syntax,
+            Pat::RestPat(it) => &it.syntax,
             Pat::SlicePat(it) => &it.syntax,
             Pat::TuplePat(it) => &it.syntax,
             Pat::TupleStructPat(it) => &it.syntax,
-            Pat::ConstBlockPat(it) => &it.syntax,
-        }
-    }
-}
-impl From<RecordFieldList> for FieldList {
-    fn from(node: RecordFieldList) -> FieldList { FieldList::RecordFieldList(node) }
-}
-impl From<TupleFieldList> for FieldList {
-    fn from(node: TupleFieldList) -> FieldList { FieldList::TupleFieldList(node) }
-}
-impl AstNode for FieldList {
-    fn can_cast(kind: SyntaxKind) -> bool { matches!(kind, RECORD_FIELD_LIST | TUPLE_FIELD_LIST) }
-    fn cast(syntax: SyntaxNode) -> Option<Self> {
-        let res = match syntax.kind() {
-            RECORD_FIELD_LIST => FieldList::RecordFieldList(RecordFieldList { syntax }),
-            TUPLE_FIELD_LIST => FieldList::TupleFieldList(TupleFieldList { syntax }),
-            _ => return None,
-        };
-        Some(res)
-    }
-    fn syntax(&self) -> &SyntaxNode {
-        match self {
-            FieldList::RecordFieldList(it) => &it.syntax,
-            FieldList::TupleFieldList(it) => &it.syntax,
+            Pat::WildcardPat(it) => &it.syntax,
         }
     }
 }
-impl From<Enum> for Adt {
-    fn from(node: Enum) -> Adt { Adt::Enum(node) }
+impl From<ExprStmt> for Stmt {
+    fn from(node: ExprStmt) -> Stmt { Stmt::ExprStmt(node) }
 }
-impl From<Struct> for Adt {
-    fn from(node: Struct) -> Adt { Adt::Struct(node) }
+impl From<Item> for Stmt {
+    fn from(node: Item) -> Stmt { Stmt::Item(node) }
 }
-impl From<Union> for Adt {
-    fn from(node: Union) -> Adt { Adt::Union(node) }
+impl From<LetStmt> for Stmt {
+    fn from(node: LetStmt) -> Stmt { Stmt::LetStmt(node) }
 }
-impl AstNode for Adt {
-    fn can_cast(kind: SyntaxKind) -> bool { matches!(kind, ENUM | STRUCT | UNION) }
-    fn cast(syntax: SyntaxNode) -> Option<Self> {
-        let res = match syntax.kind() {
-            ENUM => Adt::Enum(Enum { syntax }),
-            STRUCT => Adt::Struct(Struct { syntax }),
-            UNION => Adt::Union(Union { syntax }),
-            _ => return None,
-        };
-        Some(res)
-    }
-    fn syntax(&self) -> &SyntaxNode {
-        match self {
-            Adt::Enum(it) => &it.syntax,
-            Adt::Struct(it) => &it.syntax,
-            Adt::Union(it) => &it.syntax,
-        }
-    }
+impl From<ArrayType> for Type {
+    fn from(node: ArrayType) -> Type { Type::ArrayType(node) }
 }
-impl From<Const> for AssocItem {
-    fn from(node: Const) -> AssocItem { AssocItem::Const(node) }
+impl From<DynTraitType> for Type {
+    fn from(node: DynTraitType) -> Type { Type::DynTraitType(node) }
 }
-impl From<Fn> for AssocItem {
-    fn from(node: Fn) -> AssocItem { AssocItem::Fn(node) }
+impl From<FnPtrType> for Type {
+    fn from(node: FnPtrType) -> Type { Type::FnPtrType(node) }
 }
-impl From<MacroCall> for AssocItem {
-    fn from(node: MacroCall) -> AssocItem { AssocItem::MacroCall(node) }
+impl From<ForType> for Type {
+    fn from(node: ForType) -> Type { Type::ForType(node) }
 }
-impl From<TypeAlias> for AssocItem {
-    fn from(node: TypeAlias) -> AssocItem { AssocItem::TypeAlias(node) }
+impl From<ImplTraitType> for Type {
+    fn from(node: ImplTraitType) -> Type { Type::ImplTraitType(node) }
 }
-impl AstNode for AssocItem {
-    fn can_cast(kind: SyntaxKind) -> bool { matches!(kind, CONST | FN | MACRO_CALL | TYPE_ALIAS) }
-    fn cast(syntax: SyntaxNode) -> Option<Self> {
-        let res = match syntax.kind() {
-            CONST => AssocItem::Const(Const { syntax }),
-            FN => AssocItem::Fn(Fn { syntax }),
-            MACRO_CALL => AssocItem::MacroCall(MacroCall { syntax }),
-            TYPE_ALIAS => AssocItem::TypeAlias(TypeAlias { syntax }),
-            _ => return None,
-        };
-        Some(res)
-    }
-    fn syntax(&self) -> &SyntaxNode {
-        match self {
-            AssocItem::Const(it) => &it.syntax,
-            AssocItem::Fn(it) => &it.syntax,
-            AssocItem::MacroCall(it) => &it.syntax,
-            AssocItem::TypeAlias(it) => &it.syntax,
-        }
-    }
+impl From<InferType> for Type {
+    fn from(node: InferType) -> Type { Type::InferType(node) }
 }
-impl From<Fn> for ExternItem {
-    fn from(node: Fn) -> ExternItem { ExternItem::Fn(node) }
+impl From<MacroType> for Type {
+    fn from(node: MacroType) -> Type { Type::MacroType(node) }
 }
-impl From<MacroCall> for ExternItem {
-    fn from(node: MacroCall) -> ExternItem { ExternItem::MacroCall(node) }
+impl From<NeverType> for Type {
+    fn from(node: NeverType) -> Type { Type::NeverType(node) }
 }
-impl From<Static> for ExternItem {
-    fn from(node: Static) -> ExternItem { ExternItem::Static(node) }
+impl From<ParenType> for Type {
+    fn from(node: ParenType) -> Type { Type::ParenType(node) }
 }
-impl From<TypeAlias> for ExternItem {
-    fn from(node: TypeAlias) -> ExternItem { ExternItem::TypeAlias(node) }
+impl From<PathType> for Type {
+    fn from(node: PathType) -> Type { Type::PathType(node) }
 }
-impl AstNode for ExternItem {
-    fn can_cast(kind: SyntaxKind) -> bool { matches!(kind, FN | MACRO_CALL | STATIC | TYPE_ALIAS) }
-    fn cast(syntax: SyntaxNode) -> Option<Self> {
-        let res = match syntax.kind() {
-            FN => ExternItem::Fn(Fn { syntax }),
-            MACRO_CALL => ExternItem::MacroCall(MacroCall { syntax }),
-            STATIC => ExternItem::Static(Static { syntax }),
-            TYPE_ALIAS => ExternItem::TypeAlias(TypeAlias { syntax }),
-            _ => return None,
-        };
-        Some(res)
-    }
-    fn syntax(&self) -> &SyntaxNode {
-        match self {
-            ExternItem::Fn(it) => &it.syntax,
-            ExternItem::MacroCall(it) => &it.syntax,
-            ExternItem::Static(it) => &it.syntax,
-            ExternItem::TypeAlias(it) => &it.syntax,
-        }
-    }
+impl From<PtrType> for Type {
+    fn from(node: PtrType) -> Type { Type::PtrType(node) }
 }
-impl From<ConstParam> for GenericParam {
-    fn from(node: ConstParam) -> GenericParam { GenericParam::ConstParam(node) }
+impl From<RefType> for Type {
+    fn from(node: RefType) -> Type { Type::RefType(node) }
 }
-impl From<LifetimeParam> for GenericParam {
-    fn from(node: LifetimeParam) -> GenericParam { GenericParam::LifetimeParam(node) }
+impl From<SliceType> for Type {
+    fn from(node: SliceType) -> Type { Type::SliceType(node) }
 }
-impl From<TypeParam> for GenericParam {
-    fn from(node: TypeParam) -> GenericParam { GenericParam::TypeParam(node) }
+impl From<TupleType> for Type {
+    fn from(node: TupleType) -> Type { Type::TupleType(node) }
 }
-impl AstNode for GenericParam {
+impl AstNode for Type {
     fn can_cast(kind: SyntaxKind) -> bool {
-        matches!(kind, CONST_PARAM | LIFETIME_PARAM | TYPE_PARAM)
+        matches!(
+            kind,
+            ARRAY_TYPE
+                | DYN_TRAIT_TYPE
+                | FN_PTR_TYPE
+                | FOR_TYPE
+                | IMPL_TRAIT_TYPE
+                | INFER_TYPE
+                | MACRO_TYPE
+                | NEVER_TYPE
+                | PAREN_TYPE
+                | PATH_TYPE
+                | PTR_TYPE
+                | REF_TYPE
+                | SLICE_TYPE
+                | TUPLE_TYPE
+        )
     }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         let res = match syntax.kind() {
-            CONST_PARAM => GenericParam::ConstParam(ConstParam { syntax }),
-            LIFETIME_PARAM => GenericParam::LifetimeParam(LifetimeParam { syntax }),
-            TYPE_PARAM => GenericParam::TypeParam(TypeParam { syntax }),
+            ARRAY_TYPE => Type::ArrayType(ArrayType { syntax }),
+            DYN_TRAIT_TYPE => Type::DynTraitType(DynTraitType { syntax }),
+            FN_PTR_TYPE => Type::FnPtrType(FnPtrType { syntax }),
+            FOR_TYPE => Type::ForType(ForType { syntax }),
+            IMPL_TRAIT_TYPE => Type::ImplTraitType(ImplTraitType { syntax }),
+            INFER_TYPE => Type::InferType(InferType { syntax }),
+            MACRO_TYPE => Type::MacroType(MacroType { syntax }),
+            NEVER_TYPE => Type::NeverType(NeverType { syntax }),
+            PAREN_TYPE => Type::ParenType(ParenType { syntax }),
+            PATH_TYPE => Type::PathType(PathType { syntax }),
+            PTR_TYPE => Type::PtrType(PtrType { syntax }),
+            REF_TYPE => Type::RefType(RefType { syntax }),
+            SLICE_TYPE => Type::SliceType(SliceType { syntax }),
+            TUPLE_TYPE => Type::TupleType(TupleType { syntax }),
             _ => return None,
         };
         Some(res)
     }
     fn syntax(&self) -> &SyntaxNode {
         match self {
-            GenericParam::ConstParam(it) => &it.syntax,
-            GenericParam::LifetimeParam(it) => &it.syntax,
-            GenericParam::TypeParam(it) => &it.syntax,
+            Type::ArrayType(it) => &it.syntax,
+            Type::DynTraitType(it) => &it.syntax,
+            Type::FnPtrType(it) => &it.syntax,
+            Type::ForType(it) => &it.syntax,
+            Type::ImplTraitType(it) => &it.syntax,
+            Type::InferType(it) => &it.syntax,
+            Type::MacroType(it) => &it.syntax,
+            Type::NeverType(it) => &it.syntax,
+            Type::ParenType(it) => &it.syntax,
+            Type::PathType(it) => &it.syntax,
+            Type::PtrType(it) => &it.syntax,
+            Type::RefType(it) => &it.syntax,
+            Type::SliceType(it) => &it.syntax,
+            Type::TupleType(it) => &it.syntax,
         }
     }
 }
@@ -4123,78 +4123,78 @@ impl AstNode for AnyHasAttrs {
     fn can_cast(kind: SyntaxKind) -> bool {
         matches!(
             kind,
-            MACRO_CALL
-                | SOURCE_FILE
-                | CONST
-                | ENUM
-                | EXTERN_BLOCK
-                | EXTERN_CRATE
-                | FN
-                | IMPL
-                | MACRO_RULES
-                | MACRO_DEF
-                | MODULE
-                | STATIC
-                | STRUCT
-                | TRAIT
-                | TRAIT_ALIAS
-                | TYPE_ALIAS
-                | UNION
-                | USE
-                | ITEM_LIST
-                | BLOCK_EXPR
-                | SELF_PARAM
-                | PARAM
-                | RECORD_FIELD
-                | TUPLE_FIELD
-                | VARIANT
-                | ASSOC_ITEM_LIST
-                | EXTERN_ITEM_LIST
-                | CONST_PARAM
-                | LIFETIME_PARAM
-                | TYPE_PARAM
-                | LET_STMT
-                | ARRAY_EXPR
+            ARRAY_EXPR
                 | ASM_EXPR
+                | ASSOC_ITEM_LIST
                 | AWAIT_EXPR
+                | BECOME_EXPR
                 | BIN_EXPR
+                | BLOCK_EXPR
                 | BREAK_EXPR
                 | CALL_EXPR
                 | CAST_EXPR
                 | CLOSURE_EXPR
+                | CONST
+                | CONST_PARAM
                 | CONTINUE_EXPR
+                | ENUM
+                | EXTERN_BLOCK
+                | EXTERN_CRATE
+                | EXTERN_ITEM_LIST
                 | FIELD_EXPR
+                | FN
                 | FOR_EXPR
                 | FORMAT_ARGS_EXPR
+                | IDENT_PAT
                 | IF_EXPR
+                | IMPL
                 | INDEX_EXPR
+                | ITEM_LIST
+                | LET_EXPR
+                | LET_STMT
+                | LIFETIME_PARAM
                 | LITERAL
                 | LOOP_EXPR
+                | MACRO_CALL
+                | MACRO_DEF
+                | MACRO_RULES
+                | MATCH_ARM
+                | MATCH_ARM_LIST
                 | MATCH_EXPR
                 | METHOD_CALL_EXPR
+                | MODULE
                 | OFFSET_OF_EXPR
+                | PARAM
                 | PAREN_EXPR
                 | PATH_EXPR
                 | PREFIX_EXPR
                 | RANGE_EXPR
+                | RECORD_EXPR_FIELD
+                | RECORD_EXPR_FIELD_LIST
+                | RECORD_FIELD
+                | RECORD_PAT_FIELD
                 | REF_EXPR
+                | REST_PAT
                 | RETURN_EXPR
-                | BECOME_EXPR
+                | SELF_PARAM
+                | SOURCE_FILE
+                | STATIC
+                | STMT_LIST
+                | STRUCT
+                | TRAIT
+                | TRAIT_ALIAS
                 | TRY_EXPR
                 | TUPLE_EXPR
+                | TUPLE_FIELD
+                | TYPE_ALIAS
+                | TYPE_PARAM
+                | UNDERSCORE_EXPR
+                | UNION
+                | USE
+                | VARIANT
                 | WHILE_EXPR
-                | YIELD_EXPR
                 | YEET_EXPR
-                | LET_EXPR
-                | UNDERSCORE_EXPR
-                | STMT_LIST
-                | RECORD_EXPR_FIELD_LIST
-                | RECORD_EXPR_FIELD
-                | MATCH_ARM_LIST
-                | MATCH_ARM
-                | IDENT_PAT
-                | REST_PAT
-                | RECORD_PAT_FIELD
+                | YIELD_EXPR
         )
     }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4212,26 +4212,26 @@ impl AstNode for AnyHasDocComments {
     fn can_cast(kind: SyntaxKind) -> bool {
         matches!(
             kind,
-            MACRO_CALL
-                | SOURCE_FILE
-                | CONST
+            CONST
                 | ENUM
                 | EXTERN_BLOCK
                 | EXTERN_CRATE
                 | FN
                 | IMPL
-                | MACRO_RULES
+                | MACRO_CALL
                 | MACRO_DEF
+                | MACRO_RULES
                 | MODULE
+                | RECORD_FIELD
+                | SOURCE_FILE
                 | STATIC
                 | STRUCT
                 | TRAIT
                 | TRAIT_ALIAS
+                | TUPLE_FIELD
                 | TYPE_ALIAS
                 | UNION
                 | USE
-                | RECORD_FIELD
-                | TUPLE_FIELD
                 | VARIANT
         )
     }
@@ -4275,7 +4275,7 @@ impl AnyHasModuleItem {
     }
 }
 impl AstNode for AnyHasModuleItem {
-    fn can_cast(kind: SyntaxKind) -> bool { matches!(kind, MACRO_ITEMS | SOURCE_FILE | ITEM_LIST) }
+    fn can_cast(kind: SyntaxKind) -> bool { matches!(kind, ITEM_LIST | MACRO_ITEMS | SOURCE_FILE) }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         Self::can_cast(syntax.kind()).then_some(AnyHasModuleItem { syntax })
     }
@@ -4292,25 +4292,25 @@ impl AstNode for AnyHasName {
         matches!(
             kind,
             CONST
+                | CONST_PARAM
                 | ENUM
                 | FN
-                | MACRO_RULES
+                | FORMAT_ARGS_ARG
+                | IDENT_PAT
                 | MACRO_DEF
+                | MACRO_RULES
                 | MODULE
+                | RECORD_FIELD
+                | RENAME
+                | SELF_PARAM
                 | STATIC
                 | STRUCT
                 | TRAIT
                 | TRAIT_ALIAS
                 | TYPE_ALIAS
+                | TYPE_PARAM
                 | UNION
-                | RENAME
-                | SELF_PARAM
-                | RECORD_FIELD
                 | VARIANT
-                | CONST_PARAM
-                | TYPE_PARAM
-                | FORMAT_ARGS_ARG
-                | IDENT_PAT
         )
     }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4328,7 +4328,7 @@ impl AstNode for AnyHasTypeBounds {
     fn can_cast(kind: SyntaxKind) -> bool {
         matches!(
             kind,
-            ASSOC_TYPE_ARG | TRAIT | TYPE_ALIAS | LIFETIME_PARAM | TYPE_PARAM | WHERE_PRED
+            ASSOC_TYPE_ARG | LIFETIME_PARAM | TRAIT | TYPE_ALIAS | TYPE_PARAM | WHERE_PRED
         )
     }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4351,18 +4351,18 @@ impl AstNode for AnyHasVisibility {
                 | EXTERN_CRATE
                 | FN
                 | IMPL
-                | MACRO_RULES
                 | MACRO_DEF
+                | MACRO_RULES
                 | MODULE
+                | RECORD_FIELD
                 | STATIC
                 | STRUCT
                 | TRAIT
                 | TRAIT_ALIAS
+                | TUPLE_FIELD
                 | TYPE_ALIAS
                 | UNION
                 | USE
-                | RECORD_FIELD
-                | TUPLE_FIELD
                 | VARIANT
         )
     }
@@ -4371,12 +4371,12 @@ impl AstNode for AnyHasVisibility {
     }
     fn syntax(&self) -> &SyntaxNode { &self.syntax }
 }
-impl std::fmt::Display for Type {
+impl std::fmt::Display for Adt {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for GenericArg {
+impl std::fmt::Display for AssocItem {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
@@ -4386,477 +4386,477 @@ impl std::fmt::Display for Expr {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Item {
+impl std::fmt::Display for ExternItem {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Stmt {
+impl std::fmt::Display for FieldList {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Pat {
+impl std::fmt::Display for GenericArg {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for FieldList {
+impl std::fmt::Display for GenericParam {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Adt {
+impl std::fmt::Display for Item {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for AssocItem {
+impl std::fmt::Display for Pat {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for ExternItem {
+impl std::fmt::Display for Stmt {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for GenericParam {
+impl std::fmt::Display for Type {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Name {
+impl std::fmt::Display for Abi {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for NameRef {
+impl std::fmt::Display for ArgList {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Lifetime {
+impl std::fmt::Display for ArrayExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Path {
+impl std::fmt::Display for ArrayType {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for PathSegment {
+impl std::fmt::Display for AsmExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for GenericArgList {
+impl std::fmt::Display for AssocItemList {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for ParamList {
+impl std::fmt::Display for AssocTypeArg {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for RetType {
+impl std::fmt::Display for Attr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for PathType {
+impl std::fmt::Display for AwaitExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for TypeArg {
+impl std::fmt::Display for BecomeExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for AssocTypeArg {
+impl std::fmt::Display for BinExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for LifetimeArg {
+impl std::fmt::Display for BlockExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for ConstArg {
+impl std::fmt::Display for BoxPat {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for TypeBoundList {
+impl std::fmt::Display for BreakExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for MacroCall {
+impl std::fmt::Display for CallExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Attr {
+impl std::fmt::Display for CastExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for TokenTree {
+impl std::fmt::Display for ClosureExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for MacroItems {
+impl std::fmt::Display for Const {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for MacroEagerInput {
+impl std::fmt::Display for ConstArg {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for MacroStmts {
+impl std::fmt::Display for ConstBlockPat {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for SourceFile {
+impl std::fmt::Display for ConstParam {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Const {
+impl std::fmt::Display for ContinueExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Enum {
+impl std::fmt::Display for DynTraitType {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for ExternBlock {
+impl std::fmt::Display for Enum {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for ExternCrate {
+impl std::fmt::Display for ExprStmt {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Fn {
+impl std::fmt::Display for ExternBlock {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Impl {
+impl std::fmt::Display for ExternCrate {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for MacroRules {
+impl std::fmt::Display for ExternItemList {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for MacroDef {
+impl std::fmt::Display for FieldExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Module {
+impl std::fmt::Display for Fn {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Static {
+impl std::fmt::Display for FnPtrType {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Struct {
+impl std::fmt::Display for ForExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Trait {
+impl std::fmt::Display for ForType {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for TraitAlias {
+impl std::fmt::Display for FormatArgsArg {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for TypeAlias {
+impl std::fmt::Display for FormatArgsExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Union {
+impl std::fmt::Display for GenericArgList {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Use {
+impl std::fmt::Display for GenericParamList {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Visibility {
+impl std::fmt::Display for IdentPat {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for ItemList {
+impl std::fmt::Display for IfExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Rename {
+impl std::fmt::Display for Impl {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for UseTree {
+impl std::fmt::Display for ImplTraitType {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for UseTreeList {
+impl std::fmt::Display for IndexExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Abi {
+impl std::fmt::Display for InferType {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for GenericParamList {
+impl std::fmt::Display for ItemList {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for WhereClause {
+impl std::fmt::Display for Label {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for BlockExpr {
+impl std::fmt::Display for LetElse {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for SelfParam {
+impl std::fmt::Display for LetExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Param {
+impl std::fmt::Display for LetStmt {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for RecordFieldList {
+impl std::fmt::Display for Lifetime {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for TupleFieldList {
+impl std::fmt::Display for LifetimeArg {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for RecordField {
+impl std::fmt::Display for LifetimeParam {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for TupleField {
+impl std::fmt::Display for Literal {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for VariantList {
+impl std::fmt::Display for LiteralPat {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Variant {
+impl std::fmt::Display for LoopExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for AssocItemList {
+impl std::fmt::Display for MacroCall {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for ExternItemList {
+impl std::fmt::Display for MacroDef {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for ConstParam {
+impl std::fmt::Display for MacroEagerInput {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for LifetimeParam {
+impl std::fmt::Display for MacroExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for TypeParam {
+impl std::fmt::Display for MacroItems {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for WherePred {
+impl std::fmt::Display for MacroPat {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Meta {
+impl std::fmt::Display for MacroRules {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for ExprStmt {
+impl std::fmt::Display for MacroStmts {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for LetStmt {
+impl std::fmt::Display for MacroType {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for LetElse {
+impl std::fmt::Display for MatchArm {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for ArrayExpr {
+impl std::fmt::Display for MatchArmList {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for AsmExpr {
+impl std::fmt::Display for MatchExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for AwaitExpr {
+impl std::fmt::Display for MatchGuard {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for BinExpr {
+impl std::fmt::Display for Meta {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for BreakExpr {
+impl std::fmt::Display for MethodCallExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for CallExpr {
+impl std::fmt::Display for Module {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for CastExpr {
+impl std::fmt::Display for Name {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for ClosureExpr {
+impl std::fmt::Display for NameRef {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for ContinueExpr {
+impl std::fmt::Display for NeverType {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for FieldExpr {
+impl std::fmt::Display for OffsetOfExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for ForExpr {
+impl std::fmt::Display for OrPat {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for FormatArgsExpr {
+impl std::fmt::Display for Param {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for IfExpr {
+impl std::fmt::Display for ParamList {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for IndexExpr {
+impl std::fmt::Display for ParenExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Literal {
+impl std::fmt::Display for ParenPat {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for LoopExpr {
+impl std::fmt::Display for ParenType {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for MacroExpr {
+impl std::fmt::Display for Path {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for MatchExpr {
+impl std::fmt::Display for PathExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for MethodCallExpr {
+impl std::fmt::Display for PathPat {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for OffsetOfExpr {
+impl std::fmt::Display for PathSegment {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for ParenExpr {
+impl std::fmt::Display for PathType {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for PathExpr {
+impl std::fmt::Display for PrefixExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for PrefixExpr {
+impl std::fmt::Display for PtrType {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
@@ -4866,162 +4866,162 @@ impl std::fmt::Display for RangeExpr {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for RecordExpr {
+impl std::fmt::Display for RangePat {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for RefExpr {
+impl std::fmt::Display for RecordExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for ReturnExpr {
+impl std::fmt::Display for RecordExprField {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for BecomeExpr {
+impl std::fmt::Display for RecordExprFieldList {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for TryExpr {
+impl std::fmt::Display for RecordField {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for TupleExpr {
+impl std::fmt::Display for RecordFieldList {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for WhileExpr {
+impl std::fmt::Display for RecordPat {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for YieldExpr {
+impl std::fmt::Display for RecordPatField {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for YeetExpr {
+impl std::fmt::Display for RecordPatFieldList {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for LetExpr {
+impl std::fmt::Display for RefExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for UnderscoreExpr {
+impl std::fmt::Display for RefPat {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for FormatArgsArg {
+impl std::fmt::Display for RefType {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for StmtList {
+impl std::fmt::Display for Rename {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for Label {
+impl std::fmt::Display for RestPat {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for RecordExprFieldList {
+impl std::fmt::Display for RetType {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for RecordExprField {
+impl std::fmt::Display for ReturnExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for ArgList {
+impl std::fmt::Display for SelfParam {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for MatchArmList {
+impl std::fmt::Display for SlicePat {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for MatchArm {
+impl std::fmt::Display for SliceType {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for MatchGuard {
+impl std::fmt::Display for SourceFile {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for ArrayType {
+impl std::fmt::Display for Static {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for DynTraitType {
+impl std::fmt::Display for StmtList {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for FnPtrType {
+impl std::fmt::Display for Struct {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for ForType {
+impl std::fmt::Display for TokenTree {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for ImplTraitType {
+impl std::fmt::Display for Trait {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for InferType {
+impl std::fmt::Display for TraitAlias {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for MacroType {
+impl std::fmt::Display for TryExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for NeverType {
+impl std::fmt::Display for TupleExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for ParenType {
+impl std::fmt::Display for TupleField {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for PtrType {
+impl std::fmt::Display for TupleFieldList {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for RefType {
+impl std::fmt::Display for TuplePat {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for SliceType {
+impl std::fmt::Display for TupleStructPat {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
@@ -5031,97 +5031,97 @@ impl std::fmt::Display for TupleType {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for TypeBound {
+impl std::fmt::Display for TypeAlias {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for IdentPat {
+impl std::fmt::Display for TypeArg {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for BoxPat {
+impl std::fmt::Display for TypeBound {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for RestPat {
+impl std::fmt::Display for TypeBoundList {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for LiteralPat {
+impl std::fmt::Display for TypeParam {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for MacroPat {
+impl std::fmt::Display for UnderscoreExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for OrPat {
+impl std::fmt::Display for Union {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for ParenPat {
+impl std::fmt::Display for Use {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for PathPat {
+impl std::fmt::Display for UseTree {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for WildcardPat {
+impl std::fmt::Display for UseTreeList {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for RangePat {
+impl std::fmt::Display for Variant {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for RecordPat {
+impl std::fmt::Display for VariantList {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for RefPat {
+impl std::fmt::Display for Visibility {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for SlicePat {
+impl std::fmt::Display for WhereClause {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for TuplePat {
+impl std::fmt::Display for WherePred {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for TupleStructPat {
+impl std::fmt::Display for WhileExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for ConstBlockPat {
+impl std::fmt::Display for WildcardPat {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for RecordPatFieldList {
+impl std::fmt::Display for YeetExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
 }
-impl std::fmt::Display for RecordPatField {
+impl std::fmt::Display for YieldExpr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(self.syntax(), f)
     }
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/tokens.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/tokens.rs
index f5863e9efe0..651a8ebbf79 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/tokens.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/tokens.rs
@@ -7,16 +7,16 @@ use crate::{
 };
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Whitespace {
+pub struct Byte {
     pub(crate) syntax: SyntaxToken,
 }
-impl std::fmt::Display for Whitespace {
+impl std::fmt::Display for Byte {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(&self.syntax, f)
     }
 }
-impl AstToken for Whitespace {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == WHITESPACE }
+impl AstToken for Byte {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == BYTE }
     fn cast(syntax: SyntaxToken) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -28,16 +28,16 @@ impl AstToken for Whitespace {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Comment {
+pub struct ByteString {
     pub(crate) syntax: SyntaxToken,
 }
-impl std::fmt::Display for Comment {
+impl std::fmt::Display for ByteString {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(&self.syntax, f)
     }
 }
-impl AstToken for Comment {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == COMMENT }
+impl AstToken for ByteString {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == BYTE_STRING }
     fn cast(syntax: SyntaxToken) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -49,16 +49,16 @@ impl AstToken for Comment {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct String {
+pub struct CString {
     pub(crate) syntax: SyntaxToken,
 }
-impl std::fmt::Display for String {
+impl std::fmt::Display for CString {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(&self.syntax, f)
     }
 }
-impl AstToken for String {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == STRING }
+impl AstToken for CString {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == C_STRING }
     fn cast(syntax: SyntaxToken) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -70,16 +70,16 @@ impl AstToken for String {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct ByteString {
+pub struct Char {
     pub(crate) syntax: SyntaxToken,
 }
-impl std::fmt::Display for ByteString {
+impl std::fmt::Display for Char {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(&self.syntax, f)
     }
 }
-impl AstToken for ByteString {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == BYTE_STRING }
+impl AstToken for Char {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == CHAR }
     fn cast(syntax: SyntaxToken) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -91,16 +91,16 @@ impl AstToken for ByteString {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct CString {
+pub struct Comment {
     pub(crate) syntax: SyntaxToken,
 }
-impl std::fmt::Display for CString {
+impl std::fmt::Display for Comment {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(&self.syntax, f)
     }
 }
-impl AstToken for CString {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == C_STRING }
+impl AstToken for Comment {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == COMMENT }
     fn cast(syntax: SyntaxToken) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -112,16 +112,16 @@ impl AstToken for CString {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct IntNumber {
+pub struct FloatNumber {
     pub(crate) syntax: SyntaxToken,
 }
-impl std::fmt::Display for IntNumber {
+impl std::fmt::Display for FloatNumber {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(&self.syntax, f)
     }
 }
-impl AstToken for IntNumber {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == INT_NUMBER }
+impl AstToken for FloatNumber {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == FLOAT_NUMBER }
     fn cast(syntax: SyntaxToken) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -133,16 +133,16 @@ impl AstToken for IntNumber {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct FloatNumber {
+pub struct Ident {
     pub(crate) syntax: SyntaxToken,
 }
-impl std::fmt::Display for FloatNumber {
+impl std::fmt::Display for Ident {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(&self.syntax, f)
     }
 }
-impl AstToken for FloatNumber {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == FLOAT_NUMBER }
+impl AstToken for Ident {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == IDENT }
     fn cast(syntax: SyntaxToken) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -154,16 +154,16 @@ impl AstToken for FloatNumber {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Char {
+pub struct IntNumber {
     pub(crate) syntax: SyntaxToken,
 }
-impl std::fmt::Display for Char {
+impl std::fmt::Display for IntNumber {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(&self.syntax, f)
     }
 }
-impl AstToken for Char {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == CHAR }
+impl AstToken for IntNumber {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == INT_NUMBER }
     fn cast(syntax: SyntaxToken) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -175,16 +175,16 @@ impl AstToken for Char {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Byte {
+pub struct String {
     pub(crate) syntax: SyntaxToken,
 }
-impl std::fmt::Display for Byte {
+impl std::fmt::Display for String {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(&self.syntax, f)
     }
 }
-impl AstToken for Byte {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == BYTE }
+impl AstToken for String {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == STRING }
     fn cast(syntax: SyntaxToken) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
@@ -196,16 +196,16 @@ impl AstToken for Byte {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct Ident {
+pub struct Whitespace {
     pub(crate) syntax: SyntaxToken,
 }
-impl std::fmt::Display for Ident {
+impl std::fmt::Display for Whitespace {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         std::fmt::Display::fmt(&self.syntax, f)
     }
 }
-impl AstToken for Ident {
-    fn can_cast(kind: SyntaxKind) -> bool { kind == IDENT }
+impl AstToken for Whitespace {
+    fn can_cast(kind: SyntaxKind) -> bool { kind == WHITESPACE }
     fn cast(syntax: SyntaxToken) -> Option<Self> {
         if Self::can_cast(syntax.kind()) {
             Some(Self { syntax })
diff --git a/src/tools/rust-analyzer/crates/syntax/src/tests.rs b/src/tools/rust-analyzer/crates/syntax/src/tests.rs
index 5400071c4b6..439daa358a8 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/tests.rs
@@ -1,8 +1,3 @@
-#[cfg(not(feature = "in-rust-tree"))]
-mod ast_src;
-#[cfg(not(feature = "in-rust-tree"))]
-mod sourcegen_ast;
-
 use std::{
     fs,
     path::{Path, PathBuf},
@@ -82,7 +77,25 @@ fn reparse_fuzz_tests() {
 fn self_hosting_parsing() {
     let crates_dir = project_root().join("crates");
 
-    let mut files = ::sourcegen::list_rust_files(&crates_dir);
+    let mut files = Vec::new();
+    let mut work = vec![crates_dir.to_path_buf()];
+    while let Some(dir) = work.pop() {
+        for entry in dir.read_dir().unwrap() {
+            let entry = entry.unwrap();
+            let file_type = entry.file_type().unwrap();
+            let path = entry.path();
+            let file_name = &path.file_name().unwrap_or_default().to_str().unwrap_or_default();
+            let is_hidden = file_name.starts_with('.');
+            if !is_hidden {
+                if file_type.is_dir() {
+                    work.push(path);
+                } else if file_type.is_file() && file_name.ends_with(".rs") {
+                    files.push(path);
+                }
+            }
+        }
+    }
+
     files.retain(|path| {
         // Get all files which are not in the crates/syntax/test_data folder
         !path.components().any(|component| component.as_os_str() == "test_data")
diff --git a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
index 8cf65d11c6c..c8d785f83e8 100644
--- a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
@@ -2,8 +2,8 @@
 use std::{iter, mem, ops::Not, str::FromStr, sync};
 
 use base_db::{
-    CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Edition, Env,
-    FileChange, FileSet, LangCrateOrigin, SourceDatabaseExt, SourceRoot, Version, VfsPath,
+    CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Env, FileChange,
+    FileSet, LangCrateOrigin, SourceDatabaseExt, SourceRoot, Version, VfsPath,
 };
 use cfg::CfgOptions;
 use hir_expand::{
@@ -14,7 +14,7 @@ use hir_expand::{
     },
 };
 use rustc_hash::FxHashMap;
-use span::{FileId, FilePosition, FileRange, Span};
+use span::{Edition, FileId, FilePosition, FileRange, Span};
 use test_utils::{
     extract_range_or_offset, Fixture, FixtureWithProjectMeta, RangeOrOffset, CURSOR_MARKER,
     ESCAPED_CURSOR_MARKER,
@@ -137,7 +137,10 @@ impl ChangeFixture {
         let mut crate_deps = Vec::new();
         let mut default_crate_root: Option<FileId> = None;
         let mut default_cfg = CfgOptions::default();
-        let mut default_env = Env::new_for_test_fixture();
+        let mut default_env = Env::from_iter([(
+            String::from("__ra_is_test_fixture"),
+            String::from("__ra_is_test_fixture"),
+        )]);
 
         let mut file_set = FileSet::default();
         let mut current_source_root_kind = SourceRootKind::Local;
@@ -262,7 +265,10 @@ impl ChangeFixture {
                 None,
                 Default::default(),
                 Default::default(),
-                Env::new_for_test_fixture(),
+                Env::from_iter([(
+                    String::from("__ra_is_test_fixture"),
+                    String::from("__ra_is_test_fixture"),
+                )]),
                 false,
                 CrateOrigin::Lang(LangCrateOrigin::Core),
             );
@@ -298,7 +304,10 @@ impl ChangeFixture {
                 None,
                 Default::default(),
                 Default::default(),
-                Env::new_for_test_fixture(),
+                Env::from_iter([(
+                    String::from("__ra_is_test_fixture"),
+                    String::from("__ra_is_test_fixture"),
+                )]),
                 true,
                 CrateOrigin::Local { repo: None, name: None },
             );
@@ -393,7 +402,7 @@ pub fn mirror(input: TokenStream) -> TokenStream {
             .into(),
             ProcMacro {
                 name: "mirror".into(),
-                kind: ProcMacroKind::FuncLike,
+                kind: ProcMacroKind::Bang,
                 expander: sync::Arc::new(MirrorProcMacroExpander),
                 disabled: false,
             },
@@ -408,7 +417,7 @@ pub fn shorten(input: TokenStream) -> TokenStream {
             .into(),
             ProcMacro {
                 name: "shorten".into(),
-                kind: ProcMacroKind::FuncLike,
+                kind: ProcMacroKind::Bang,
                 expander: sync::Arc::new(ShortenProcMacroExpander),
                 disabled: false,
             },
diff --git a/src/tools/rust-analyzer/crates/toolchain/Cargo.toml b/src/tools/rust-analyzer/crates/toolchain/Cargo.toml
index f9b120772f0..c85efd432b0 100644
--- a/src/tools/rust-analyzer/crates/toolchain/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/toolchain/Cargo.toml
@@ -13,6 +13,7 @@ doctest = false
 
 [dependencies]
 home = "0.5.4"
+camino.workspace = true
 
 [lints]
-workspace = true
\ No newline at end of file
+workspace = true
diff --git a/src/tools/rust-analyzer/crates/toolchain/src/lib.rs b/src/tools/rust-analyzer/crates/toolchain/src/lib.rs
index a77fed585af..b577723612d 100644
--- a/src/tools/rust-analyzer/crates/toolchain/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/toolchain/src/lib.rs
@@ -2,10 +2,9 @@
 
 #![warn(rust_2018_idioms, unused_lifetimes)]
 
-use std::{
-    env, iter,
-    path::{Path, PathBuf},
-};
+use std::{env, iter, path::PathBuf};
+
+use camino::{Utf8Path, Utf8PathBuf};
 
 #[derive(Copy, Clone)]
 pub enum Tool {
@@ -16,7 +15,7 @@ pub enum Tool {
 }
 
 impl Tool {
-    pub fn proxy(self) -> Option<PathBuf> {
+    pub fn proxy(self) -> Option<Utf8PathBuf> {
         cargo_proxy(self.name())
     }
 
@@ -33,7 +32,7 @@ impl Tool {
     ///      example: for cargo, this tries all paths in $PATH with appended `cargo`, returning the
     ///      first that exists
     /// 4) If all else fails, we just try to use the executable name directly
-    pub fn prefer_proxy(self) -> PathBuf {
+    pub fn prefer_proxy(self) -> Utf8PathBuf {
         invoke(&[cargo_proxy, lookup_as_env_var, lookup_in_path], self.name())
     }
 
@@ -50,11 +49,11 @@ impl Tool {
     ///      example: for cargo, this tries $CARGO_HOME/bin/cargo, or ~/.cargo/bin/cargo if $CARGO_HOME is unset.
     ///      It seems that this is a reasonable place to try for cargo, rustc, and rustup
     /// 4) If all else fails, we just try to use the executable name directly
-    pub fn path(self) -> PathBuf {
+    pub fn path(self) -> Utf8PathBuf {
         invoke(&[lookup_as_env_var, lookup_in_path, cargo_proxy], self.name())
     }
 
-    pub fn path_in(self, path: &Path) -> Option<PathBuf> {
+    pub fn path_in(self, path: &Utf8Path) -> Option<Utf8PathBuf> {
         probe_for_binary(path.join(self.name()))
     }
 
@@ -68,42 +67,50 @@ impl Tool {
     }
 }
 
-fn invoke(list: &[fn(&str) -> Option<PathBuf>], executable: &str) -> PathBuf {
+fn invoke(list: &[fn(&str) -> Option<Utf8PathBuf>], executable: &str) -> Utf8PathBuf {
     list.iter().find_map(|it| it(executable)).unwrap_or_else(|| executable.into())
 }
 
 /// Looks up the binary as its SCREAMING upper case in the env variables.
-fn lookup_as_env_var(executable_name: &str) -> Option<PathBuf> {
-    env::var_os(executable_name.to_ascii_uppercase()).map(Into::into)
+fn lookup_as_env_var(executable_name: &str) -> Option<Utf8PathBuf> {
+    env::var_os(executable_name.to_ascii_uppercase())
+        .map(PathBuf::from)
+        .map(Utf8PathBuf::try_from)
+        .and_then(Result::ok)
 }
 
 /// Looks up the binary in the cargo home directory if it exists.
-fn cargo_proxy(executable_name: &str) -> Option<PathBuf> {
+fn cargo_proxy(executable_name: &str) -> Option<Utf8PathBuf> {
     let mut path = get_cargo_home()?;
     path.push("bin");
     path.push(executable_name);
     probe_for_binary(path)
 }
 
-fn get_cargo_home() -> Option<PathBuf> {
+fn get_cargo_home() -> Option<Utf8PathBuf> {
     if let Some(path) = env::var_os("CARGO_HOME") {
-        return Some(path.into());
+        return Utf8PathBuf::try_from(PathBuf::from(path)).ok();
     }
 
     if let Some(mut path) = home::home_dir() {
         path.push(".cargo");
-        return Some(path);
+        return Utf8PathBuf::try_from(path).ok();
     }
 
     None
 }
 
-fn lookup_in_path(exec: &str) -> Option<PathBuf> {
+fn lookup_in_path(exec: &str) -> Option<Utf8PathBuf> {
     let paths = env::var_os("PATH").unwrap_or_default();
-    env::split_paths(&paths).map(|path| path.join(exec)).find_map(probe_for_binary)
+    env::split_paths(&paths)
+        .map(|path| path.join(exec))
+        .map(PathBuf::from)
+        .map(Utf8PathBuf::try_from)
+        .filter_map(Result::ok)
+        .find_map(probe_for_binary)
 }
 
-pub fn probe_for_binary(path: PathBuf) -> Option<PathBuf> {
+pub fn probe_for_binary(path: Utf8PathBuf) -> Option<Utf8PathBuf> {
     let with_extension = match env::consts::EXE_EXTENSION {
         "" => None,
         it => Some(path.with_extension(it)),
diff --git a/src/tools/rust-analyzer/crates/tt/Cargo.toml b/src/tools/rust-analyzer/crates/tt/Cargo.toml
index 77683fd48af..c96f088cdc5 100644
--- a/src/tools/rust-analyzer/crates/tt/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/tt/Cargo.toml
@@ -17,8 +17,5 @@ text-size.workspace = true
 
 stdx.workspace = true
 
-# FIXME: Remove this dependency once the `Span` trait is gone (that is once Span::DUMMY has been removed)
-span.workspace = true
-
 [lints]
-workspace = true
\ No newline at end of file
+workspace = true
diff --git a/src/tools/rust-analyzer/crates/tt/src/lib.rs b/src/tools/rust-analyzer/crates/tt/src/lib.rs
index 28289a6431e..ab0efff6512 100644
--- a/src/tools/rust-analyzer/crates/tt/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/tt/src/lib.rs
@@ -11,18 +11,13 @@ use stdx::impl_from;
 pub use smol_str::SmolStr;
 pub use text_size::{TextRange, TextSize};
 
-pub trait Span: std::fmt::Debug + Copy + Sized + Eq {}
-
-impl<Ctx> Span for span::SpanData<Ctx> where span::SpanData<Ctx>: std::fmt::Debug + Copy + Sized + Eq
-{}
-
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum TokenTree<S> {
     Leaf(Leaf<S>),
     Subtree(Subtree<S>),
 }
 impl_from!(Leaf<S>, Subtree<S> for TokenTree);
-impl<S: Span> TokenTree<S> {
+impl<S: Copy> TokenTree<S> {
     pub fn empty(span: S) -> Self {
         Self::Subtree(Subtree {
             delimiter: Delimiter::invisible_spanned(span),
@@ -72,7 +67,7 @@ pub struct Subtree<S> {
     pub token_trees: Box<[TokenTree<S>]>,
 }
 
-impl<S: Span> Subtree<S> {
+impl<S: Copy> Subtree<S> {
     pub fn empty(span: DelimSpan<S>) -> Self {
         Subtree { delimiter: Delimiter::invisible_delim_spanned(span), token_trees: Box::new([]) }
     }
@@ -114,7 +109,7 @@ pub struct Delimiter<S> {
     pub kind: DelimiterKind,
 }
 
-impl<S: Span> Delimiter<S> {
+impl<S: Copy> Delimiter<S> {
     pub const fn invisible_spanned(span: S) -> Self {
         Delimiter { open: span, close: span, kind: DelimiterKind::Invisible }
     }
diff --git a/src/tools/rust-analyzer/crates/vfs-notify/src/lib.rs b/src/tools/rust-analyzer/crates/vfs-notify/src/lib.rs
index 15a0ea5409a..4cfdec2b5c5 100644
--- a/src/tools/rust-analyzer/crates/vfs-notify/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/vfs-notify/src/lib.rs
@@ -136,7 +136,7 @@ impl NotifyActor {
                     Message::Invalidate(path) => {
                         let contents = read(path.as_path());
                         let files = vec![(path, contents)];
-                        self.send(loader::Message::Loaded { files });
+                        self.send(loader::Message::Changed { files });
                     }
                 },
                 Event::NotifyEvent(event) => {
@@ -205,7 +205,7 @@ impl NotifyActor {
                             if !entry.file_type().is_dir() {
                                 return true;
                             }
-                            let path = AbsPath::assert(entry.path());
+                            let path = entry.path();
                             root == path
                                 || dirs.exclude.iter().chain(&dirs.include).all(|it| it != path)
                         });
@@ -214,7 +214,7 @@ impl NotifyActor {
                         let depth = entry.depth();
                         let is_dir = entry.file_type().is_dir();
                         let is_file = entry.file_type().is_file();
-                        let abs_path = AbsPathBuf::assert(entry.into_path());
+                        let abs_path = AbsPathBuf::try_from(entry.into_path()).unwrap();
                         if depth < 2 && is_dir {
                             self.send(make_message(abs_path.clone()));
                         }
diff --git a/src/tools/rust-analyzer/crates/vfs/src/lib.rs b/src/tools/rust-analyzer/crates/vfs/src/lib.rs
index 824ce398703..ddd6bbe3f7a 100644
--- a/src/tools/rust-analyzer/crates/vfs/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/vfs/src/lib.rs
@@ -91,12 +91,21 @@ impl nohash_hasher::IsEnabled for FileId {}
 pub struct Vfs {
     interner: PathInterner,
     data: Vec<FileState>,
+    // FIXME: This should be a HashMap<FileId, ChangeFile>
+    // right now we do a nasty deduplication in GlobalState::process_changes that would be a lot
+    // easier to handle here on insertion.
     changes: Vec<ChangedFile>,
+    // The above FIXME would then also get rid of this probably
+    created_this_cycle: Vec<FileId>,
 }
 
-#[derive(Copy, PartialEq, PartialOrd, Clone)]
+#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
 pub enum FileState {
+    /// The file has been created this cycle.
+    Created,
+    /// The file exists.
     Exists,
+    /// The file is deleted.
     Deleted,
 }
 
@@ -121,6 +130,16 @@ impl ChangedFile {
         matches!(self.change, Change::Create(_) | Change::Delete)
     }
 
+    /// Returns `true` if the change is [`Create`](ChangeKind::Create).
+    pub fn is_created(&self) -> bool {
+        matches!(self.change, Change::Create(_))
+    }
+
+    /// Returns `true` if the change is [`Modify`](ChangeKind::Modify).
+    pub fn is_modified(&self) -> bool {
+        matches!(self.change, Change::Modify(_))
+    }
+
     pub fn kind(&self) -> ChangeKind {
         match self.change {
             Change::Create(_) => ChangeKind::Create,
@@ -155,7 +174,9 @@ pub enum ChangeKind {
 impl Vfs {
     /// Id of the given path if it exists in the `Vfs` and is not deleted.
     pub fn file_id(&self, path: &VfsPath) -> Option<FileId> {
-        self.interner.get(path).filter(|&it| matches!(self.get(it), FileState::Exists))
+        self.interner
+            .get(path)
+            .filter(|&it| matches!(self.get(it), FileState::Exists | FileState::Created))
     }
 
     /// File path corresponding to the given `file_id`.
@@ -173,7 +194,9 @@ impl Vfs {
     pub fn iter(&self) -> impl Iterator<Item = (FileId, &VfsPath)> + '_ {
         (0..self.data.len())
             .map(|it| FileId(it as u32))
-            .filter(move |&file_id| matches!(self.get(file_id), FileState::Exists))
+            .filter(move |&file_id| {
+                matches!(self.get(file_id), FileState::Exists | FileState::Created)
+            })
             .map(move |file_id| {
                 let path = self.interner.lookup(file_id);
                 (file_id, path)
@@ -188,27 +211,43 @@ impl Vfs {
     /// [`FileId`] for it.
     pub fn set_file_contents(&mut self, path: VfsPath, contents: Option<Vec<u8>>) -> bool {
         let file_id = self.alloc_file_id(path);
-        let change_kind = match (self.get(file_id), contents) {
+        let state = self.get(file_id);
+        let change_kind = match (state, contents) {
             (FileState::Deleted, None) => return false,
             (FileState::Deleted, Some(v)) => Change::Create(v),
-            (FileState::Exists, None) => Change::Delete,
-            (FileState::Exists, Some(v)) => Change::Modify(v),
+            (FileState::Exists | FileState::Created, None) => Change::Delete,
+            (FileState::Exists | FileState::Created, Some(v)) => Change::Modify(v),
+        };
+        self.data[file_id.0 as usize] = match change_kind {
+            Change::Create(_) => {
+                self.created_this_cycle.push(file_id);
+                FileState::Created
+            }
+            // If the file got created this cycle, make sure we keep it that way even
+            // if a modify comes in
+            Change::Modify(_) if matches!(state, FileState::Created) => FileState::Created,
+            Change::Modify(_) => FileState::Exists,
+            Change::Delete => FileState::Deleted,
         };
         let changed_file = ChangedFile { file_id, change: change_kind };
-        self.data[file_id.0 as usize] =
-            if changed_file.exists() { FileState::Exists } else { FileState::Deleted };
         self.changes.push(changed_file);
         true
     }
 
     /// Drain and returns all the changes in the `Vfs`.
     pub fn take_changes(&mut self) -> Vec<ChangedFile> {
+        for file_id in self.created_this_cycle.drain(..) {
+            if self.data[file_id.0 as usize] == FileState::Created {
+                // downgrade the file from `Created` to `Exists` as the cycle is done
+                self.data[file_id.0 as usize] = FileState::Exists;
+            }
+        }
         mem::take(&mut self.changes)
     }
 
     /// Provides a panic-less way to verify file_id validity.
     pub fn exists(&self, file_id: FileId) -> bool {
-        matches!(self.get(file_id), FileState::Exists)
+        matches!(self.get(file_id), FileState::Exists | FileState::Created)
     }
 
     /// Returns the id associated with `path`
diff --git a/src/tools/rust-analyzer/crates/vfs/src/loader.rs b/src/tools/rust-analyzer/crates/vfs/src/loader.rs
index c3d1ff7271a..3af91b1af81 100644
--- a/src/tools/rust-analyzer/crates/vfs/src/loader.rs
+++ b/src/tools/rust-analyzer/crates/vfs/src/loader.rs
@@ -58,7 +58,7 @@ pub enum Message {
         /// The [`Config`] version.
         config_version: u32,
     },
-    /// The handle loaded the following files' content.
+    /// The handle loaded the following files' content for the first time.
     Loaded { files: Vec<(AbsPathBuf, Option<Vec<u8>>)> },
     /// The handle loaded the following files' content.
     Changed { files: Vec<(AbsPathBuf, Option<Vec<u8>>)> },
diff --git a/src/tools/rust-analyzer/crates/vfs/src/vfs_path.rs b/src/tools/rust-analyzer/crates/vfs/src/vfs_path.rs
index 52ada32bdfd..2d3fb9d88c8 100644
--- a/src/tools/rust-analyzer/crates/vfs/src/vfs_path.rs
+++ b/src/tools/rust-analyzer/crates/vfs/src/vfs_path.rs
@@ -326,7 +326,7 @@ impl VirtualPath {
     }
 
     fn strip_prefix(&self, base: &VirtualPath) -> Option<&RelPath> {
-        <_ as AsRef<std::path::Path>>::as_ref(&self.0)
+        <_ as AsRef<paths::Utf8Path>>::as_ref(&self.0)
             .strip_prefix(&base.0)
             .ok()
             .map(RelPath::new_unchecked)
diff --git a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
index cf9ad5fe04d..939b1819c7e 100644
--- a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
+++ b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
@@ -1,5 +1,5 @@
 <!---
-lsp/ext.rs hash: 61f485497d6e8e88
+lsp/ext.rs hash: 223f48a89a5126a0
 
 If you need to change the above hash to make the test pass, please check if you
 need to adjust this doc as well and ping this issue:
@@ -417,7 +417,7 @@ interface TestItem {
     // A human readable name for this test
     label: string;
     // The kind of this test item. Based on the kind,
-	// an icon is chosen by the editor. 
+	// an icon is chosen by the editor.
     kind: "package" | "module" | "test";
     // True if this test may have children not available eagerly
     canResolveChildren: boolean;
@@ -440,7 +440,11 @@ interface DiscoverTestResults {
     // For each test which its id is in this list, the response
     // contains all tests that are children of this test, and
     // client should remove old tests not included in the response.
-    scope: string[];
+    scope: string[] | undefined;
+    // For each file which its uri is in this list, the response
+    // contains all tests that are located in this file, and
+    // client should remove old tests not included in the response.
+    scopeFile: lc.TextDocumentIdentifier[] | undefined;    
 }
 ```
 
@@ -492,9 +496,9 @@ a `experimental/endRunTest` when is done.
 **Notification:** `ChangeTestStateParams`
 
 ```typescript
-type TestState = { tag: "passed" } 
+type TestState = { tag: "passed" }
     | {
-        tag: "failed"; 
+        tag: "failed";
         // The standard error of the test, containing the panic message. Clients should
         // render it similar to a terminal, and e.g. handle ansi colors.
         message: string;
diff --git a/src/tools/rust-analyzer/docs/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc
index 5e782b78311..c4024f6d282 100644
--- a/src/tools/rust-analyzer/docs/user/generated_config.adoc
+++ b/src/tools/rust-analyzer/docs/user/generated_config.adoc
@@ -520,6 +520,11 @@ How to render the offset information in a memory layout hover.
 --
 How to render the size information in a memory layout hover.
 --
+[[rust-analyzer.hover.show.structFields]]rust-analyzer.hover.show.structFields (default: `null`)::
++
+--
+How many fields of a struct to display when hovering a struct.
+--
 [[rust-analyzer.hover.show.traitAssocItems]]rust-analyzer.hover.show.traitAssocItems (default: `null`)::
 +
 --
diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json
index c34b8e25de0..c3ea1ceeb69 100644
--- a/src/tools/rust-analyzer/editors/code/package.json
+++ b/src/tools/rust-analyzer/editors/code/package.json
@@ -1144,6 +1144,15 @@
                         }
                     ]
                 },
+                "rust-analyzer.hover.show.structFields": {
+                    "markdownDescription": "How many fields of a struct to display when hovering a struct.",
+                    "default": null,
+                    "type": [
+                        "null",
+                        "integer"
+                    ],
+                    "minimum": 0
+                },
                 "rust-analyzer.hover.show.traitAssocItems": {
                     "markdownDescription": "How many associated items of a trait to display when hovering a trait.",
                     "default": null,
diff --git a/src/tools/rust-analyzer/editors/code/src/config.ts b/src/tools/rust-analyzer/editors/code/src/config.ts
index 92a816bfbcb..e676bc0826c 100644
--- a/src/tools/rust-analyzer/editors/code/src/config.ts
+++ b/src/tools/rust-analyzer/editors/code/src/config.ts
@@ -19,7 +19,7 @@ export class Config {
     configureLang: vscode.Disposable | undefined;
 
     readonly rootSection = "rust-analyzer";
-    private readonly requiresReloadOpts = [
+    private readonly requiresServerReloadOpts = [
         "cargo",
         "procMacro",
         "serverPath",
@@ -27,6 +27,10 @@ export class Config {
         "files",
     ].map((opt) => `${this.rootSection}.${opt}`);
 
+    private readonly requiresWindowReloadOpts = ["testExplorer"].map(
+        (opt) => `${this.rootSection}.${opt}`,
+    );
+
     readonly package: {
         version: string;
         releaseTag: string | null;
@@ -66,18 +70,31 @@ export class Config {
 
         this.configureLanguage();
 
-        const requiresReloadOpt = this.requiresReloadOpts.find((opt) =>
+        const requiresWindowReloadOpt = this.requiresWindowReloadOpts.find((opt) =>
+            event.affectsConfiguration(opt),
+        );
+
+        if (requiresWindowReloadOpt) {
+            const message = `Changing "${requiresWindowReloadOpt}" requires a window reload`;
+            const userResponse = await vscode.window.showInformationMessage(message, "Reload now");
+
+            if (userResponse) {
+                await vscode.commands.executeCommand("workbench.action.reloadWindow");
+            }
+        }
+
+        const requiresServerReloadOpt = this.requiresServerReloadOpts.find((opt) =>
             event.affectsConfiguration(opt),
         );
 
-        if (!requiresReloadOpt) return;
+        if (!requiresServerReloadOpt) return;
 
         if (this.restartServerOnConfigChange) {
             await vscode.commands.executeCommand("rust-analyzer.restartServer");
             return;
         }
 
-        const message = `Changing "${requiresReloadOpt}" requires a server restart`;
+        const message = `Changing "${requiresServerReloadOpt}" requires a server restart`;
         const userResponse = await vscode.window.showInformationMessage(message, "Restart now");
 
         if (userResponse) {
diff --git a/src/tools/rust-analyzer/editors/code/src/debug.ts b/src/tools/rust-analyzer/editors/code/src/debug.ts
index 3fc63fc7d81..bad1f48de85 100644
--- a/src/tools/rust-analyzer/editors/code/src/debug.ts
+++ b/src/tools/rust-analyzer/editors/code/src/debug.ts
@@ -81,8 +81,8 @@ async function getDebugConfiguration(
     if (!editor) return;
 
     const knownEngines: Record<string, DebugConfigProvider> = {
-        "ms-vscode.cpptools": getCCppDebugConfig,
         "vadimcn.vscode-lldb": getCodeLldbDebugConfig,
+        "ms-vscode.cpptools": getCCppDebugConfig,
         "webfreak.debug": getNativeDebugConfig,
     };
     const debugOptions = ctx.config.debug;
@@ -203,6 +203,10 @@ function getCCppDebugConfig(
         cwd: cargoWorkspace || runnable.args.workspaceRoot,
         sourceFileMap,
         env,
+        // See https://github.com/rust-lang/rust-analyzer/issues/16901#issuecomment-2024486941
+        osx: {
+            MIMode: "lldb",
+        },
     };
 }
 
diff --git a/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts b/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts
index ca8106371b0..9a7a4aae959 100644
--- a/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts
+++ b/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts
@@ -83,7 +83,11 @@ export type TestItem = {
     range?: lc.Range | undefined;
     runnable?: Runnable | undefined;
 };
-export type DiscoverTestResults = { tests: TestItem[]; scope: string[] };
+export type DiscoverTestResults = {
+    tests: TestItem[];
+    scope: string[] | undefined;
+    scopeFile: lc.TextDocumentIdentifier[] | undefined;
+};
 export type TestState =
     | { tag: "failed"; message: string }
     | { tag: "passed" }
diff --git a/src/tools/rust-analyzer/editors/code/src/run.ts b/src/tools/rust-analyzer/editors/code/src/run.ts
index fc3f1acce54..02ccbb6956a 100644
--- a/src/tools/rust-analyzer/editors/code/src/run.ts
+++ b/src/tools/rust-analyzer/editors/code/src/run.ts
@@ -2,6 +2,7 @@ import * as vscode from "vscode";
 import type * as lc from "vscode-languageclient";
 import * as ra from "./lsp_ext";
 import * as tasks from "./tasks";
+import * as toolchain from "./toolchain";
 
 import type { CtxInit } from "./ctx";
 import { makeDebugConfig } from "./debug";
@@ -111,12 +112,22 @@ export async function createTask(runnable: ra.Runnable, config: Config): Promise
         throw `Unexpected runnable kind: ${runnable.kind}`;
     }
 
-    const args = createArgs(runnable);
+    let program: string;
+    let args = createArgs(runnable);
+    if (runnable.args.overrideCargo) {
+        // Split on spaces to allow overrides like "wrapper cargo".
+        const cargoParts = runnable.args.overrideCargo.split(" ");
 
-    const definition: tasks.CargoTaskDefinition = {
+        program = unwrapUndefinable(cargoParts[0]);
+        args = [...cargoParts.slice(1), ...args];
+    } else {
+        program = await toolchain.cargoPath();
+    }
+
+    const definition: tasks.RustTargetDefinition = {
         type: tasks.TASK_TYPE,
-        command: args[0], // run, test, etc...
-        args: args.slice(1),
+        program,
+        args,
         cwd: runnable.args.workspaceRoot || ".",
         env: prepareEnv(runnable, config.runnablesExtraEnv),
         overrideCargo: runnable.args.overrideCargo,
@@ -124,22 +135,21 @@ export async function createTask(runnable: ra.Runnable, config: Config): Promise
 
     // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
     const target = vscode.workspace.workspaceFolders![0]; // safe, see main activate()
-    const cargoTask = await tasks.buildCargoTask(
+    const task = await tasks.buildRustTask(
         target,
         definition,
         runnable.label,
-        args,
         config.problemMatcher,
         config.cargoRunner,
         true,
     );
 
-    cargoTask.presentationOptions.clear = true;
+    task.presentationOptions.clear = true;
     // Sadly, this doesn't prevent focus stealing if the terminal is currently
     // hidden, and will become revealed due to task execution.
-    cargoTask.presentationOptions.focus = false;
+    task.presentationOptions.focus = false;
 
-    return cargoTask;
+    return task;
 }
 
 export function createArgs(runnable: ra.Runnable): string[] {
diff --git a/src/tools/rust-analyzer/editors/code/src/tasks.ts b/src/tools/rust-analyzer/editors/code/src/tasks.ts
index 1d5ab82aa04..89abb37b0eb 100644
--- a/src/tools/rust-analyzer/editors/code/src/tasks.ts
+++ b/src/tools/rust-analyzer/editors/code/src/tasks.ts
@@ -2,22 +2,20 @@ import * as vscode from "vscode";
 import * as toolchain from "./toolchain";
 import type { Config } from "./config";
 import { log } from "./util";
-import { unwrapUndefinable } from "./undefinable";
 
 // This ends up as the `type` key in tasks.json. RLS also uses `cargo` and
 // our configuration should be compatible with it so use the same key.
 export const TASK_TYPE = "cargo";
 export const TASK_SOURCE = "rust";
 
-export interface CargoTaskDefinition extends vscode.TaskDefinition {
-    command?: string;
-    args?: string[];
+export interface RustTargetDefinition extends vscode.TaskDefinition {
+    program: string;
+    args: string[];
     cwd?: string;
     env?: { [key: string]: string };
-    overrideCargo?: string;
 }
 
-class CargoTaskProvider implements vscode.TaskProvider {
+class RustTaskProvider implements vscode.TaskProvider {
     private readonly config: Config;
 
     constructor(config: Config) {
@@ -39,14 +37,15 @@ class CargoTaskProvider implements vscode.TaskProvider {
             { command: "run", group: undefined },
         ];
 
+        const cargoPath = await toolchain.cargoPath();
+
         const tasks: vscode.Task[] = [];
         for (const workspaceTarget of vscode.workspace.workspaceFolders || []) {
             for (const def of defs) {
-                const vscodeTask = await buildCargoTask(
+                const vscodeTask = await buildRustTask(
                     workspaceTarget,
-                    { type: TASK_TYPE, command: def.command },
+                    { type: TASK_TYPE, program: cargoPath, args: [def.command] },
                     `cargo ${def.command}`,
-                    [def.command],
                     this.config.problemMatcher,
                     this.config.cargoRunner,
                 );
@@ -63,15 +62,13 @@ class CargoTaskProvider implements vscode.TaskProvider {
         // we need to inform VSCode how to execute that command by creating
         // a ShellExecution for it.
 
-        const definition = task.definition as CargoTaskDefinition;
+        const definition = task.definition as RustTargetDefinition;
 
-        if (definition.type === TASK_TYPE && definition.command) {
-            const args = [definition.command].concat(definition.args ?? []);
-            return await buildCargoTask(
+        if (definition.type === TASK_TYPE) {
+            return await buildRustTask(
                 task.scope,
                 definition,
                 task.name,
-                args,
                 this.config.problemMatcher,
                 this.config.cargoRunner,
             );
@@ -81,11 +78,10 @@ class CargoTaskProvider implements vscode.TaskProvider {
     }
 }
 
-export async function buildCargoTask(
+export async function buildRustTask(
     scope: vscode.WorkspaceFolder | vscode.TaskScope | undefined,
-    definition: CargoTaskDefinition,
+    definition: RustTargetDefinition,
     name: string,
-    args: string[],
     problemMatcher: string[],
     customRunner?: string,
     throwOnError: boolean = false,
@@ -95,7 +91,12 @@ export async function buildCargoTask(
     if (customRunner) {
         const runnerCommand = `${customRunner}.buildShellExecution`;
         try {
-            const runnerArgs = { kind: TASK_TYPE, args, cwd: definition.cwd, env: definition.env };
+            const runnerArgs = {
+                kind: TASK_TYPE,
+                args: definition.args,
+                cwd: definition.cwd,
+                env: definition.env,
+            };
             const customExec = await vscode.commands.executeCommand(runnerCommand, runnerArgs);
             if (customExec) {
                 if (customExec instanceof vscode.ShellExecution) {
@@ -113,16 +114,7 @@ export async function buildCargoTask(
     }
 
     if (!exec) {
-        // Check whether we must use a user-defined substitute for cargo.
-        // Split on spaces to allow overrides like "wrapper cargo".
-        const overrideCargo = definition.overrideCargo ?? definition.overrideCargo;
-        const cargoPath = await toolchain.cargoPath();
-        const cargoCommand = overrideCargo?.split(" ") ?? [cargoPath];
-
-        const fullCommand = [...cargoCommand, ...args];
-
-        const processName = unwrapUndefinable(fullCommand[0]);
-        exec = new vscode.ProcessExecution(processName, fullCommand.slice(1), definition);
+        exec = new vscode.ProcessExecution(definition.program, definition.args, definition);
     }
 
     return new vscode.Task(
@@ -138,6 +130,6 @@ export async function buildCargoTask(
 }
 
 export function activateTaskProvider(config: Config): vscode.Disposable {
-    const provider = new CargoTaskProvider(config);
+    const provider = new RustTaskProvider(config);
     return vscode.tasks.registerTaskProvider(TASK_TYPE, provider);
 }
diff --git a/src/tools/rust-analyzer/editors/code/src/test_explorer.ts b/src/tools/rust-analyzer/editors/code/src/test_explorer.ts
index ac4ffb19263..de41d2a57ec 100644
--- a/src/tools/rust-analyzer/editors/code/src/test_explorer.ts
+++ b/src/tools/rust-analyzer/editors/code/src/test_explorer.ts
@@ -12,6 +12,7 @@ export const prepareTestExplorer = (
 ) => {
     let currentTestRun: vscode.TestRun | undefined;
     let idToTestMap: Map<string, vscode.TestItem> = new Map();
+    const fileToTestMap: Map<string, vscode.TestItem[]> = new Map();
     const idToRunnableMap: Map<string, ra.Runnable> = new Map();
 
     testController.createRunProfile(
@@ -59,6 +60,18 @@ export const prepareTestExplorer = (
         false,
     );
 
+    const deleteTest = (item: vscode.TestItem, parentList: vscode.TestItemCollection) => {
+        parentList.delete(item.id);
+        idToTestMap.delete(item.id);
+        idToRunnableMap.delete(item.id);
+        if (item.uri) {
+            fileToTestMap.set(
+                item.uri.toString(),
+                fileToTestMap.get(item.uri.toString())!.filter((t) => t.id !== item.id),
+            );
+        }
+    };
+
     const addTest = (item: ra.TestItem) => {
         const parentList = item.parent
             ? idToTestMap.get(item.parent)!.children
@@ -76,7 +89,7 @@ export const prepareTestExplorer = (
                 oldTest.range = range;
                 return;
             }
-            parentList.delete(item.id);
+            deleteTest(oldTest, parentList);
         }
         const iconToVscodeMap = {
             package: "package",
@@ -91,6 +104,12 @@ export const prepareTestExplorer = (
         test.range = range;
         test.canResolveChildren = item.canResolveChildren;
         idToTestMap.set(item.id, test);
+        if (uri) {
+            if (!fileToTestMap.has(uri.toString())) {
+                fileToTestMap.set(uri.toString(), []);
+            }
+            fileToTestMap.get(uri.toString())!.push(test);
+        }
         if (item.runnable) {
             idToRunnableMap.set(item.id, item.runnable);
         }
@@ -98,33 +117,47 @@ export const prepareTestExplorer = (
     };
 
     const addTestGroup = (testsAndScope: ra.DiscoverTestResults) => {
-        const { tests, scope } = testsAndScope;
+        const { tests, scope, scopeFile } = testsAndScope;
         const testSet: Set<string> = new Set();
         for (const test of tests) {
             addTest(test);
             testSet.add(test.id);
         }
         // FIXME(hack_recover_crate_name): We eagerly resolve every test if we got a lazy top level response (detected
-        // by `!scope`). ctx is not a good thing and wastes cpu and memory unnecessarily, so we should remove it.
-        if (!scope) {
+        // by checking that `scope` is empty). This is not a good thing and wastes cpu and memory unnecessarily, so we
+        // should remove it.
+        if (!scope && !scopeFile) {
             for (const test of tests) {
                 void testController.resolveHandler!(idToTestMap.get(test.id));
             }
         }
-        if (!scope) {
-            return;
+        if (scope) {
+            const recursivelyRemove = (tests: vscode.TestItemCollection) => {
+                for (const [_, test] of tests) {
+                    if (!testSet.has(test.id)) {
+                        deleteTest(test, tests);
+                    } else {
+                        recursivelyRemove(test.children);
+                    }
+                }
+            };
+            for (const root of scope) {
+                recursivelyRemove(idToTestMap.get(root)!.children);
+            }
         }
-        const recursivelyRemove = (tests: vscode.TestItemCollection) => {
-            for (const [testId, _] of tests) {
-                if (!testSet.has(testId)) {
-                    tests.delete(testId);
-                } else {
-                    recursivelyRemove(tests.get(testId)!.children);
+        if (scopeFile) {
+            const removeByFile = (file: vscode.Uri) => {
+                const testsToBeRemoved = (fileToTestMap.get(file.toString()) || []).filter(
+                    (t) => !testSet.has(t.id),
+                );
+                for (const test of testsToBeRemoved) {
+                    const parentList = test.parent?.children || testController.items;
+                    deleteTest(test, parentList);
                 }
+            };
+            for (const file of scopeFile) {
+                removeByFile(vscode.Uri.parse(file.uri));
             }
-        };
-        for (const root of scope) {
-            recursivelyRemove(idToTestMap.get(root)!.children);
         }
     };
 
diff --git a/src/tools/rust-analyzer/xtask/Cargo.toml b/src/tools/rust-analyzer/xtask/Cargo.toml
index 5e758e0190c..a83d32e4141 100644
--- a/src/tools/rust-analyzer/xtask/Cargo.toml
+++ b/src/tools/rust-analyzer/xtask/Cargo.toml
@@ -15,6 +15,10 @@ xflags = "0.3.0"
 time = { version = "0.3", default-features = false }
 zip = { version = "0.6", default-features = false, features = ["deflate", "time"] }
 stdx.workspace = true
+proc-macro2 = "1.0.47"
+quote = "1.0.20"
+ungrammar = "1.16.1"
+itertools.workspace = true
 # Avoid adding more dependencies to this crate
 
 [lints]
diff --git a/src/tools/rust-analyzer/xtask/src/codegen.rs b/src/tools/rust-analyzer/xtask/src/codegen.rs
index 40f872a24ab..7dc1b40783c 100644
--- a/src/tools/rust-analyzer/xtask/src/codegen.rs
+++ b/src/tools/rust-analyzer/xtask/src/codegen.rs
@@ -9,6 +9,7 @@ use crate::{flags, project_root};
 
 pub(crate) mod assists_doc_tests;
 pub(crate) mod diagnostics_docs;
+mod grammar;
 mod lints;
 
 impl flags::Codegen {
@@ -20,6 +21,7 @@ impl flags::Codegen {
                 // lints::generate(self.check) Updating clones the rust repo, so don't run it unless
                 // explicitly asked for
             }
+            flags::CodegenType::Grammar => grammar::generate(self.check),
             flags::CodegenType::AssistsDocTests => assists_doc_tests::generate(self.check),
             flags::CodegenType::DiagnosticsDocs => diagnostics_docs::generate(self.check),
             flags::CodegenType::LintDefinitions => lints::generate(self.check),
diff --git a/src/tools/rust-analyzer/crates/syntax/src/tests/sourcegen_ast.rs b/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs
index 2fd7a473498..cc2fadc9750 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/tests/sourcegen_ast.rs
+++ b/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs
@@ -3,37 +3,45 @@
 //! Specifically, it generates the `SyntaxKind` enum and a number of newtype
 //! wrappers around `SyntaxNode` which implement `syntax::AstNode`.
 
-use std::{collections::BTreeSet, fmt::Write};
+#![allow(clippy::disallowed_types)]
+
+use std::{
+    collections::{BTreeSet, HashSet},
+    fmt::Write,
+    fs,
+};
 
 use itertools::Itertools;
 use proc_macro2::{Punct, Spacing};
 use quote::{format_ident, quote};
-use rustc_hash::FxHashSet;
 use ungrammar::{Grammar, Rule};
 
-use crate::tests::ast_src::{
-    AstEnumSrc, AstNodeSrc, AstSrc, Cardinality, Field, KindsSrc, KINDS_SRC,
+use crate::{
+    codegen::{add_preamble, ensure_file_contents, reformat},
+    project_root,
 };
 
-#[test]
-fn sourcegen_ast() {
+mod ast_src;
+use self::ast_src::{AstEnumSrc, AstNodeSrc, AstSrc, Cardinality, Field, KindsSrc, KINDS_SRC};
+
+pub(crate) fn generate(check: bool) {
     let syntax_kinds = generate_syntax_kinds(KINDS_SRC);
-    let syntax_kinds_file =
-        sourcegen::project_root().join("crates/parser/src/syntax_kind/generated.rs");
-    sourcegen::ensure_file_contents(syntax_kinds_file.as_path(), &syntax_kinds);
+    let syntax_kinds_file = project_root().join("crates/parser/src/syntax_kind/generated.rs");
+    ensure_file_contents(syntax_kinds_file.as_path(), &syntax_kinds, check);
 
-    let grammar =
-        include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/rust.ungram")).parse().unwrap();
+    let grammar = fs::read_to_string(project_root().join("crates/syntax/rust.ungram"))
+        .unwrap()
+        .parse()
+        .unwrap();
     let ast = lower(&grammar);
 
     let ast_tokens = generate_tokens(&ast);
-    let ast_tokens_file =
-        sourcegen::project_root().join("crates/syntax/src/ast/generated/tokens.rs");
-    sourcegen::ensure_file_contents(ast_tokens_file.as_path(), &ast_tokens);
+    let ast_tokens_file = project_root().join("crates/syntax/src/ast/generated/tokens.rs");
+    ensure_file_contents(ast_tokens_file.as_path(), &ast_tokens, check);
 
     let ast_nodes = generate_nodes(KINDS_SRC, &ast);
-    let ast_nodes_file = sourcegen::project_root().join("crates/syntax/src/ast/generated/nodes.rs");
-    sourcegen::ensure_file_contents(ast_nodes_file.as_path(), &ast_nodes);
+    let ast_nodes_file = project_root().join("crates/syntax/src/ast/generated/nodes.rs");
+    ensure_file_contents(ast_nodes_file.as_path(), &ast_nodes, check);
 }
 
 fn generate_tokens(grammar: &AstSrc) -> String {
@@ -60,9 +68,9 @@ fn generate_tokens(grammar: &AstSrc) -> String {
         }
     });
 
-    sourcegen::add_preamble(
+    add_preamble(
         "sourcegen_ast",
-        sourcegen::reformat(
+        reformat(
             quote! {
                 use crate::{SyntaxKind::{self, *}, SyntaxToken, ast::AstToken};
                 #(#tokens)*
@@ -150,13 +158,14 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> String {
         .enums
         .iter()
         .map(|en| {
-            let variants: Vec<_> = en.variants.iter().map(|var| format_ident!("{}", var)).collect();
+            let variants: Vec<_> =
+                en.variants.iter().map(|var| format_ident!("{}", var)).sorted().collect();
             let name = format_ident!("{}", en.name);
             let kinds: Vec<_> = variants
                 .iter()
                 .map(|name| format_ident!("{}", to_upper_snake_case(&name.to_string())))
                 .collect();
-            let traits = en.traits.iter().map(|trait_name| {
+            let traits = en.traits.iter().sorted().map(|trait_name| {
                 let trait_name = format_ident!("{}", trait_name);
                 quote!(impl ast::#trait_name for #name {})
             });
@@ -212,14 +221,13 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> String {
             )
         })
         .unzip();
-
     let (any_node_defs, any_node_boilerplate_impls): (Vec<_>, Vec<_>) = grammar
         .nodes
         .iter()
         .flat_map(|node| node.traits.iter().map(move |t| (t, node)))
         .into_group_map()
         .into_iter()
-        .sorted_by_key(|(k, _)| *k)
+        .sorted_by_key(|(name, _)| *name)
         .map(|(trait_name, nodes)| {
             let name = format_ident!("Any{}", trait_name);
             let trait_name = format_ident!("{}", trait_name);
@@ -276,7 +284,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> String {
             }
         });
 
-    let defined_nodes: FxHashSet<_> = node_names.collect();
+    let defined_nodes: HashSet<_> = node_names.collect();
 
     for node in kinds
         .nodes
@@ -320,7 +328,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> String {
         }
     }
 
-    let res = sourcegen::add_preamble("sourcegen_ast", sourcegen::reformat(res));
+    let res = add_preamble("sourcegen_ast", reformat(res));
     res.replace("#[derive", "\n#[derive")
 }
 
@@ -450,7 +458,7 @@ fn generate_syntax_kinds(grammar: KindsSrc<'_>) -> String {
         }
     };
 
-    sourcegen::add_preamble("sourcegen_ast", sourcegen::reformat(ast.to_string()))
+    add_preamble("sourcegen_ast", reformat(ast.to_string()))
 }
 
 fn to_upper_snake_case(s: &str) -> String {
@@ -600,6 +608,20 @@ fn lower(grammar: &Grammar) -> AstSrc {
     extract_enums(&mut res);
     extract_struct_traits(&mut res);
     extract_enum_traits(&mut res);
+    res.nodes.sort_by_key(|it| it.name.clone());
+    res.enums.sort_by_key(|it| it.name.clone());
+    res.tokens.sort();
+    res.nodes.iter_mut().for_each(|it| {
+        it.traits.sort();
+        it.fields.sort_by_key(|it| match it {
+            Field::Token(name) => (true, name.clone()),
+            Field::Node { name, .. } => (false, name.clone()),
+        });
+    });
+    res.enums.iter_mut().for_each(|it| {
+        it.traits.sort();
+        it.variants.sort();
+    });
     res
 }
 
diff --git a/src/tools/rust-analyzer/crates/syntax/src/tests/ast_src.rs b/src/tools/rust-analyzer/xtask/src/codegen/grammar/ast_src.rs
index 8221c577892..8221c577892 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/tests/ast_src.rs
+++ b/src/tools/rust-analyzer/xtask/src/codegen/grammar/ast_src.rs
diff --git a/src/tools/rust-analyzer/xtask/src/dist.rs b/src/tools/rust-analyzer/xtask/src/dist.rs
index 7e54d19fe4d..2fe9db98cf2 100644
--- a/src/tools/rust-analyzer/xtask/src/dist.rs
+++ b/src/tools/rust-analyzer/xtask/src/dist.rs
@@ -10,7 +10,11 @@ use time::OffsetDateTime;
 use xshell::{cmd, Shell};
 use zip::{write::FileOptions, DateTime, ZipWriter};
 
-use crate::{date_iso, flags, project_root};
+use crate::{
+    date_iso,
+    flags::{self, Malloc},
+    project_root,
+};
 
 const VERSION_STABLE: &str = "0.3";
 const VERSION_NIGHTLY: &str = "0.4";
@@ -22,6 +26,7 @@ impl flags::Dist {
 
         let project_root = project_root();
         let target = Target::get(&project_root);
+        let allocator = self.allocator();
         let dist = project_root.join("dist");
         sh.remove_path(&dist)?;
         sh.create_dir(&dist)?;
@@ -33,11 +38,11 @@ impl flags::Dist {
                 // A hack to make VS Code prefer nightly over stable.
                 format!("{VERSION_NIGHTLY}.{patch_version}")
             };
-            dist_server(sh, &format!("{version}-standalone"), &target)?;
+            dist_server(sh, &format!("{version}-standalone"), &target, allocator)?;
             let release_tag = if stable { date_iso(sh)? } else { "nightly".to_owned() };
             dist_client(sh, &version, &release_tag, &target)?;
         } else {
-            dist_server(sh, "0.0.0-standalone", &target)?;
+            dist_server(sh, "0.0.0-standalone", &target, allocator)?;
         }
         Ok(())
     }
@@ -73,7 +78,12 @@ fn dist_client(
     Ok(())
 }
 
-fn dist_server(sh: &Shell, release: &str, target: &Target) -> anyhow::Result<()> {
+fn dist_server(
+    sh: &Shell,
+    release: &str,
+    target: &Target,
+    allocator: Malloc,
+) -> anyhow::Result<()> {
     let _e = sh.push_env("CFG_RELEASE", release);
     let _e = sh.push_env("CARGO_PROFILE_RELEASE_LTO", "thin");
 
@@ -87,7 +97,8 @@ fn dist_server(sh: &Shell, release: &str, target: &Target) -> anyhow::Result<()>
     }
 
     let target_name = &target.name;
-    cmd!(sh, "cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --target {target_name} --release").run()?;
+    let features = allocator.to_features();
+    cmd!(sh, "cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --target {target_name} {features...} --release").run()?;
 
     let dst = Path::new("dist").join(&target.artifact_name);
     gzip(&target.server_path, &dst.with_extension("gz"))?;
diff --git a/src/tools/rust-analyzer/xtask/src/flags.rs b/src/tools/rust-analyzer/xtask/src/flags.rs
index 681c588bd01..90665459208 100644
--- a/src/tools/rust-analyzer/xtask/src/flags.rs
+++ b/src/tools/rust-analyzer/xtask/src/flags.rs
@@ -2,7 +2,7 @@
 
 use std::str::FromStr;
 
-use crate::install::{ClientOpt, Malloc, ServerOpt};
+use crate::install::{ClientOpt, ServerOpt};
 
 xflags::xflags! {
     src "./src/flags.rs"
@@ -36,6 +36,10 @@ xflags::xflags! {
             optional --dry-run
         }
         cmd dist {
+            /// Use mimalloc allocator for server
+            optional --mimalloc
+            /// Use jemalloc allocator for server
+            optional --jemalloc
             optional --client-patch-version version: String
         }
         /// Read a changelog AsciiDoc file and update the GitHub Releases entry in Markdown.
@@ -82,33 +86,6 @@ pub enum XtaskCmd {
 }
 
 #[derive(Debug)]
-pub struct Codegen {
-    pub check: bool,
-    pub codegen_type: Option<CodegenType>,
-}
-
-#[derive(Debug, Default)]
-pub enum CodegenType {
-    #[default]
-    All,
-    AssistsDocTests,
-    DiagnosticsDocs,
-    LintDefinitions,
-}
-
-impl FromStr for CodegenType {
-    type Err = String;
-    fn from_str(s: &str) -> Result<Self, Self::Err> {
-        match s {
-            "all" => Ok(Self::All),
-            "assists-doc-tests" => Ok(Self::AssistsDocTests),
-            "diagnostics-docs" => Ok(Self::DiagnosticsDocs),
-            "lints-definitions" => Ok(Self::LintDefinitions),
-            _ => Err("Invalid option".to_owned()),
-        }
-    }
-}
-#[derive(Debug)]
 pub struct Install {
     pub client: bool,
     pub code_bin: Option<String>,
@@ -133,6 +110,8 @@ pub struct Promote {
 
 #[derive(Debug)]
 pub struct Dist {
+    pub mimalloc: bool,
+    pub jemalloc: bool,
     pub client_patch_version: Option<String>,
 }
 
@@ -144,6 +123,65 @@ pub struct PublishReleaseNotes {
 }
 
 #[derive(Debug)]
+pub struct Metrics {
+    pub measurement_type: Option<MeasurementType>,
+}
+
+#[derive(Debug)]
+pub struct Bb {
+    pub suffix: String,
+}
+
+#[derive(Debug)]
+pub struct Codegen {
+    pub codegen_type: Option<CodegenType>,
+
+    pub check: bool,
+}
+
+impl Xtask {
+    #[allow(dead_code)]
+    pub fn from_env_or_exit() -> Self {
+        Self::from_env_or_exit_()
+    }
+
+    #[allow(dead_code)]
+    pub fn from_env() -> xflags::Result<Self> {
+        Self::from_env_()
+    }
+
+    #[allow(dead_code)]
+    pub fn from_vec(args: Vec<std::ffi::OsString>) -> xflags::Result<Self> {
+        Self::from_vec_(args)
+    }
+}
+// generated end
+
+#[derive(Debug, Default)]
+pub enum CodegenType {
+    #[default]
+    All,
+    Grammar,
+    AssistsDocTests,
+    DiagnosticsDocs,
+    LintDefinitions,
+}
+
+impl FromStr for CodegenType {
+    type Err = String;
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match s {
+            "all" => Ok(Self::All),
+            "grammar" => Ok(Self::Grammar),
+            "assists-doc-tests" => Ok(Self::AssistsDocTests),
+            "diagnostics-docs" => Ok(Self::DiagnosticsDocs),
+            "lints-definitions" => Ok(Self::LintDefinitions),
+            _ => Err("Invalid option".to_owned()),
+        }
+    }
+}
+
+#[derive(Debug)]
 pub enum MeasurementType {
     Build,
     RustcTests,
@@ -183,33 +221,22 @@ impl AsRef<str> for MeasurementType {
     }
 }
 
-#[derive(Debug)]
-pub struct Metrics {
-    pub measurement_type: Option<MeasurementType>,
-}
-
-#[derive(Debug)]
-pub struct Bb {
-    pub suffix: String,
+#[derive(Clone, Copy, Debug)]
+pub(crate) enum Malloc {
+    System,
+    Mimalloc,
+    Jemalloc,
 }
 
-impl Xtask {
-    #[allow(dead_code)]
-    pub fn from_env_or_exit() -> Self {
-        Self::from_env_or_exit_()
-    }
-
-    #[allow(dead_code)]
-    pub fn from_env() -> xflags::Result<Self> {
-        Self::from_env_()
-    }
-
-    #[allow(dead_code)]
-    pub fn from_vec(args: Vec<std::ffi::OsString>) -> xflags::Result<Self> {
-        Self::from_vec_(args)
+impl Malloc {
+    pub(crate) fn to_features(self) -> &'static [&'static str] {
+        match self {
+            Malloc::System => &[][..],
+            Malloc::Mimalloc => &["--features", "mimalloc"],
+            Malloc::Jemalloc => &["--features", "jemalloc"],
+        }
     }
 }
-// generated end
 
 impl Install {
     pub(crate) fn server(&self) -> Option<ServerOpt> {
@@ -232,3 +259,15 @@ impl Install {
         Some(ClientOpt { code_bin: self.code_bin.clone() })
     }
 }
+
+impl Dist {
+    pub(crate) fn allocator(&self) -> Malloc {
+        if self.mimalloc {
+            Malloc::Mimalloc
+        } else if self.jemalloc {
+            Malloc::Jemalloc
+        } else {
+            Malloc::System
+        }
+    }
+}
diff --git a/src/tools/rust-analyzer/xtask/src/install.rs b/src/tools/rust-analyzer/xtask/src/install.rs
index dc932da80c2..72e612f9e1d 100644
--- a/src/tools/rust-analyzer/xtask/src/install.rs
+++ b/src/tools/rust-analyzer/xtask/src/install.rs
@@ -5,7 +5,7 @@ use std::{env, path::PathBuf, str};
 use anyhow::{bail, format_err, Context};
 use xshell::{cmd, Shell};
 
-use crate::flags;
+use crate::flags::{self, Malloc};
 
 impl flags::Install {
     pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> {
@@ -34,12 +34,6 @@ pub(crate) struct ServerOpt {
     pub(crate) dev_rel: bool,
 }
 
-pub(crate) enum Malloc {
-    System,
-    Mimalloc,
-    Jemalloc,
-}
-
 fn fix_path_for_mac(sh: &Shell) -> anyhow::Result<()> {
     let mut vscode_path: Vec<PathBuf> = {
         const COMMON_APP_PATH: &str =
@@ -122,7 +116,7 @@ fn install_client(sh: &Shell, client_opt: ClientOpt) -> anyhow::Result<()> {
     if !installed_extensions.contains("rust-analyzer") {
         bail!(
             "Could not install the Visual Studio Code extension. \
-            Please make sure you have at least NodeJS 12.x together with the latest version of VS Code installed and try again. \
+            Please make sure you have at least NodeJS 16.x together with the latest version of VS Code installed and try again. \
             Note that installing via xtask install does not work for VS Code Remote, instead you’ll need to install the .vsix manually."
         );
     }
@@ -131,11 +125,7 @@ fn install_client(sh: &Shell, client_opt: ClientOpt) -> anyhow::Result<()> {
 }
 
 fn install_server(sh: &Shell, opts: ServerOpt) -> anyhow::Result<()> {
-    let features = match opts.malloc {
-        Malloc::System => &[][..],
-        Malloc::Mimalloc => &["--features", "mimalloc"],
-        Malloc::Jemalloc => &["--features", "jemalloc"],
-    };
+    let features = opts.malloc.to_features();
     let profile = if opts.dev_rel { "dev-rel" } else { "release" };
 
     let cmd = cmd!(sh, "cargo install --path crates/rust-analyzer --profile={profile} --locked --force --features force-always-assert {features...}");