about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-01-08 01:08:24 +0000
committerbors <bors@rust-lang.org>2025-01-08 01:08:24 +0000
commit1f81f906893d166d05fb4839f169983f2b564cc7 (patch)
treec82ddd3825f3751a89c5816f071ca18d5f13bc6e
parent07074990a9334629d479cdc80d2ed1f7e6bc78ea (diff)
parentfd1e95538fa3b3ca87fc4f7df5e9abd918949536 (diff)
downloadrust-1f81f906893d166d05fb4839f169983f2b564cc7.tar.gz
rust-1f81f906893d166d05fb4839f169983f2b564cc7.zip
Auto merge of #135207 - lnicola:sync-from-ra, r=lnicola
Subtree update of `rust-analyzer`

r? `@ghost`
-rw-r--r--src/tools/rust-analyzer/.github/workflows/ci.yaml6
-rw-r--r--src/tools/rust-analyzer/Cargo.lock2
-rw-r--r--src/tools/rust-analyzer/Cargo.toml9
-rw-r--r--src/tools/rust-analyzer/clippy.toml4
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/input.rs19
-rw-r--r--src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs21
-rw-r--r--src/tools/rust-analyzer/crates/edition/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/attr.rs76
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/data.rs84
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs19
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/db.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs128
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs46
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/attr_resolution.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs23
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs89
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/proc_macro.rs17
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/path.rs15
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/resolver.rs103
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs89
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/builtin/attr_macro.rs62
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs706
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/builtin/fn_macro.rs349
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs250
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/db.rs46
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs17
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/eager.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs163
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/lib.rs13
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/proc_macro.rs28
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs27
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/db.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs45
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/generics.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer.rs129
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs128
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs21
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs62
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lang_items.rs1
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs20
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lib.rs9
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower.rs399
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower/diagnostics.rs36
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs116
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs164
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs29
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests.rs78
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs17
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/utils.rs17
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/variance.rs1065
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/attrs.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/diagnostics.rs52
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/display.rs17
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs230
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics.rs107
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs328
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_lifetime_to_type.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs18
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_match_to_let_else.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_nested_function_to_closure.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs14
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_glob_import.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_module.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs43
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_constant.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_fn_type_alias.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_bounds.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_param.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs720
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs13
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/utils.rs90
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/dot.rs56
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs87
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs32
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/record.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/config.rs12
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context.rs60
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs30
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/item.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/lib.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs35
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests.rs14
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs22
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs469
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs34
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs72
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/defs.rs191
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/documentation.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/search.rs24
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs147
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs165
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs18
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/annotations.rs68
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/doc_links.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/doc_links/intra_doc_links.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/expand_macro.rs9
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_definition.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/highlight_related.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover.rs35
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/render.rs92
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/tests.rs797
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs14
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/binding_mode.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/discriminant.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/param_name.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/lib.rs14
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/moniker.rs316
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/parent_module.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/references.rs20
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/rename.rs14
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/runnables.rs215
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/signature_help.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/static_index.rs11
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs18
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/typing.rs2
-rw-r--r--src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs1
-rw-r--r--src/tools/rust-analyzer/crates/load-cargo/src/lib.rs24
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/benchmark.rs113
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/expander.rs60
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs243
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs428
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/lib.rs70
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/parser.rs88
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/syntax_bridge/tests.rs101
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/input.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/output.rs4
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/shortcuts.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs325
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/json.rs (renamed from src/tools/rust-analyzer/crates/proc-macro-api/src/json.rs)0
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs (renamed from src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs)169
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg/flat.rs (renamed from src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs)247
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-api/src/lib.rs55
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs43
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv-cli/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs58
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main_loop.rs134
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/build.rs1
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs2
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/dylib.rs113
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs189
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/proc_macros.rs37
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl.rs28
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs135
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs113
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs155
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs20
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs14
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs114
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/env.rs93
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/lib.rs51
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/manifest_path.rs2
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs99
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/sysroot.rs230
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/target_data_layout.rs67
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/tests.rs79
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/toolchain_info/rustc_cfg.rs124
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/toolchain_info/target_data_layout.rs83
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/toolchain_info/target_tuple.rs105
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/toolchain_info/version.rs58
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/workspace.rs527
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt2
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/regex-metadata.json6420
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/ripgrep-metadata.json12816
-rw-r--r--src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/src/query_group.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ra-salsa/src/derived/slot.rs45
-rw-r--r--src/tools/rust-analyzer/crates/ra-salsa/src/derived_lru/slot.rs49
-rw-r--r--src/tools/rust-analyzer/crates/ra-salsa/src/input.rs14
-rw-r--r--src/tools/rust-analyzer/crates/ra-salsa/src/lib.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ra-salsa/src/lru.rs24
-rw-r--r--src/tools/rust-analyzer/crates/ra-salsa/src/runtime.rs12
-rw-r--r--src/tools/rust-analyzer/crates/ra-salsa/src/runtime/local_state.rs4
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/build.rs1
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/bin/main.rs28
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/bin/rustc_wrapper.rs1
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs4
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs4
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs7
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs18
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/scip.rs503
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs187
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs10
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs99
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs5
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs36
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs107
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs115
-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.rs17
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs41
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs3
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs15
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs1
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/test_runner.rs4
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/tests/slow-tests/main.rs4
-rw-r--r--src/tools/rust-analyzer/crates/span/src/lib.rs12
-rw-r--r--src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs217
-rw-r--r--src/tools/rust-analyzer/crates/syntax-bridge/src/tests.rs21
-rw-r--r--src/tools/rust-analyzer/crates/syntax-bridge/src/to_parser_input.rs54
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast.rs8
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs2
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/expr_ext.rs2
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs1078
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/make.rs126
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/make/quote.rs191
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs4
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs44
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs2
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edits.rs2
-rw-r--r--src/tools/rust-analyzer/crates/test-fixture/src/lib.rs175
-rw-r--r--src/tools/rust-analyzer/crates/test-utils/src/minicore.rs9
-rw-r--r--src/tools/rust-analyzer/crates/toolchain/src/lib.rs17
-rw-r--r--src/tools/rust-analyzer/crates/tt/src/buffer.rs307
-rw-r--r--src/tools/rust-analyzer/crates/tt/src/iter.rs118
-rw-r--r--src/tools/rust-analyzer/crates/tt/src/lib.rs616
-rw-r--r--src/tools/rust-analyzer/docs/dev/lsp-extensions.md2
-rw-r--r--src/tools/rust-analyzer/docs/user/generated_config.adoc67
-rw-r--r--src/tools/rust-analyzer/docs/user/manual.adoc2
-rw-r--r--src/tools/rust-analyzer/editors/code/package.json199
-rw-r--r--src/tools/rust-analyzer/editors/code/src/commands.ts26
-rw-r--r--src/tools/rust-analyzer/editors/code/src/config.ts18
-rw-r--r--src/tools/rust-analyzer/editors/code/src/ctx.ts13
-rw-r--r--src/tools/rust-analyzer/rust-version2
-rw-r--r--src/tools/rust-analyzer/xtask/src/codegen/grammar.rs25
-rw-r--r--src/tools/rust-analyzer/xtask/src/main.rs7
274 files changed, 32947 insertions, 5399 deletions
diff --git a/src/tools/rust-analyzer/.github/workflows/ci.yaml b/src/tools/rust-analyzer/.github/workflows/ci.yaml
index 46bae20054c..ec33009239c 100644
--- a/src/tools/rust-analyzer/.github/workflows/ci.yaml
+++ b/src/tools/rust-analyzer/.github/workflows/ci.yaml
@@ -6,6 +6,10 @@ on:
   pull_request:
   merge_group:
 
+concurrency:
+  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
+  cancel-in-progress: true
+
 env:
   CARGO_INCREMENTAL: 0
   CARGO_NET_RETRY: 10
@@ -103,7 +107,7 @@ jobs:
       - name: Run analysis-stats on the rust standard libraries
         if: matrix.os == 'ubuntu-latest'
         env:
-            RUSTC_BOOTSTRAP: 1
+          RUSTC_BOOTSTRAP: 1
         run: target/${{ matrix.target }}/debug/rust-analyzer analysis-stats --with-deps --no-sysroot --no-test $(rustc --print sysroot)/lib/rustlib/src/rust/library/
 
       - name: clippy
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index 2323fdf5333..48b5f3aabfc 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -1375,7 +1375,6 @@ dependencies = [
  "memmap2",
  "object 0.33.0",
  "paths",
- "proc-macro-api",
  "proc-macro-test",
  "ra-ap-rustc_lexer",
  "span",
@@ -1390,6 +1389,7 @@ version = "0.0.0"
 dependencies = [
  "proc-macro-api",
  "proc-macro-srv",
+ "tt",
 ]
 
 [[package]]
diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml
index 7f3abcccc47..9440123de70 100644
--- a/src/tools/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/Cargo.toml
@@ -79,6 +79,7 @@ span = { path = "./crates/span", version = "0.0.0" }
 stdx = { path = "./crates/stdx", version = "0.0.0" }
 syntax = { path = "./crates/syntax", version = "0.0.0" }
 syntax-bridge = { path = "./crates/syntax-bridge", version = "0.0.0" }
+test-utils = { path = "./crates/test-utils", version = "0.0.0" }
 toolchain = { path = "./crates/toolchain", version = "0.0.0" }
 tt = { path = "./crates/tt", version = "0.0.0" }
 vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" }
@@ -93,7 +94,6 @@ ra-ap-rustc_pattern_analysis = { version = "0.87", default-features = false }
 
 # local crates that aren't published to crates.io. These should not have versions.
 test-fixture = { path = "./crates/test-fixture" }
-test-utils = { path = "./crates/test-utils" }
 
 # In-tree crates that are published separately and follow semver. See lib/README.md
 line-index = { version = "0.1.2" }
@@ -203,6 +203,13 @@ new_ret_no_self = "allow"
 useless_asref = "allow"
 # Has false positives
 assigning_clones = "allow"
+# Does not work with macros
+vec_init_then_push = "allow"
+# Our tests have a lot of these
+literal_string_with_formatting_args = "allow"
+# This lint has been empowered but now also triggers on cases where its invalid to do so
+# due to it ignoring move analysis
+unnecessary_map_or = "allow"
 
 ## Following lints should be tackled at some point
 too_many_arguments = "allow"
diff --git a/src/tools/rust-analyzer/clippy.toml b/src/tools/rust-analyzer/clippy.toml
index 8032c775ab0..1046cb3d56b 100644
--- a/src/tools/rust-analyzer/clippy.toml
+++ b/src/tools/rust-analyzer/clippy.toml
@@ -3,3 +3,7 @@ disallowed-types = [
     { path = "std::collections::HashSet", reason = "use FxHashSet" },
     { path = "std::collections::hash_map::RandomState", reason = "use BuildHasherDefault<FxHasher>"}
 ]
+
+disallowed-methods = [
+    { path = "std::process::Command::new", reason = "use `toolchain::command` instead as it forces the choice of a working directory" },
+]
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 e86944eeb35..a0fc8c31eaf 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/input.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs
@@ -490,21 +490,25 @@ impl CrateGraph {
         }
     }
 
-    pub fn sort_deps(&mut self) {
-        self.arena
-            .iter_mut()
-            .for_each(|(_, data)| data.dependencies.sort_by_key(|dep| dep.crate_id));
-    }
-
     /// Extends this crate graph by adding a complete second crate
     /// graph and adjust the ids in the [`ProcMacroPaths`] accordingly.
     ///
+    /// This will deduplicate the crates of the graph where possible.
+    /// Furthermore dependencies are sorted by crate id to make deduplication easier.
+    ///
     /// Returns a map mapping `other`'s IDs to the new IDs in `self`.
     pub fn extend(
         &mut self,
         mut other: CrateGraph,
         proc_macros: &mut ProcMacroPaths,
     ) -> FxHashMap<CrateId, CrateId> {
+        // Sorting here is a bit pointless because the input is likely already sorted.
+        // However, the overhead is small and it makes the `extend` method harder to misuse.
+        self.arena
+            .iter_mut()
+            .for_each(|(_, data)| data.dependencies.sort_by_key(|dep| dep.crate_id));
+
+        let m = self.len();
         let topo = other.crates_in_topological_order();
         let mut id_map: FxHashMap<CrateId, CrateId> = FxHashMap::default();
         for topo in topo {
@@ -513,7 +517,8 @@ impl CrateGraph {
             crate_data.dependencies.iter_mut().for_each(|dep| dep.crate_id = id_map[&dep.crate_id]);
             crate_data.dependencies.sort_by_key(|dep| dep.crate_id);
 
-            let new_id = self.arena.alloc(crate_data.clone());
+            let find = self.arena.iter().take(m).find_map(|(k, v)| (v == crate_data).then_some(k));
+            let new_id = find.unwrap_or_else(|| self.arena.alloc(crate_data.clone()));
             id_map.insert(topo, new_id);
         }
 
diff --git a/src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs b/src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs
index 35c0c89c70c..84b91a527f0 100644
--- a/src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs
+++ b/src/tools/rust-analyzer/crates/cfg/src/cfg_expr.rs
@@ -45,8 +45,8 @@ impl From<CfgAtom> for CfgExpr {
 
 impl CfgExpr {
     #[cfg(feature = "tt")]
-    pub fn parse<S>(tt: &tt::Subtree<S>) -> CfgExpr {
-        next_cfg_expr(&mut tt.token_trees.iter()).unwrap_or(CfgExpr::Invalid)
+    pub fn parse<S: Copy>(tt: &tt::TopSubtree<S>) -> CfgExpr {
+        next_cfg_expr(&mut tt.iter()).unwrap_or(CfgExpr::Invalid)
     }
 
     /// Fold the cfg by querying all basic `Atom` and `KeyValue` predicates.
@@ -66,19 +66,19 @@ impl CfgExpr {
 }
 
 #[cfg(feature = "tt")]
-fn next_cfg_expr<S>(it: &mut std::slice::Iter<'_, tt::TokenTree<S>>) -> Option<CfgExpr> {
+fn next_cfg_expr<S: Copy>(it: &mut tt::iter::TtIter<'_, S>) -> Option<CfgExpr> {
     use intern::sym;
+    use tt::iter::TtElement;
 
     let name = match it.next() {
         None => return None,
-        Some(tt::TokenTree::Leaf(tt::Leaf::Ident(ident))) => ident.sym.clone(),
+        Some(TtElement::Leaf(tt::Leaf::Ident(ident))) => ident.sym.clone(),
         Some(_) => return Some(CfgExpr::Invalid),
     };
 
-    // Peek
-    let ret = match it.as_slice().first() {
-        Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) if punct.char == '=' => {
-            match it.as_slice().get(1) {
+    let ret = match it.peek() {
+        Some(TtElement::Leaf(tt::Leaf::Punct(punct))) if punct.char == '=' => {
+            match it.remaining().flat_tokens().get(1) {
                 Some(tt::TokenTree::Leaf(tt::Leaf::Literal(literal))) => {
                     it.next();
                     it.next();
@@ -87,9 +87,8 @@ fn next_cfg_expr<S>(it: &mut std::slice::Iter<'_, tt::TokenTree<S>>) -> Option<C
                 _ => return Some(CfgExpr::Invalid),
             }
         }
-        Some(tt::TokenTree::Subtree(subtree)) => {
+        Some(TtElement::Subtree(_, mut sub_it)) => {
             it.next();
-            let mut sub_it = subtree.token_trees.iter();
             let mut subs = std::iter::from_fn(|| next_cfg_expr(&mut sub_it));
             match name {
                 s if s == sym::all => CfgExpr::All(subs.collect()),
@@ -104,7 +103,7 @@ fn next_cfg_expr<S>(it: &mut std::slice::Iter<'_, tt::TokenTree<S>>) -> Option<C
     };
 
     // Eat comma separator
-    if let Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) = it.as_slice().first() {
+    if let Some(TtElement::Leaf(tt::Leaf::Punct(punct))) = it.peek() {
         if punct.char == ',' {
             it.next();
         }
diff --git a/src/tools/rust-analyzer/crates/edition/Cargo.toml b/src/tools/rust-analyzer/crates/edition/Cargo.toml
index 926b1e1cd41..0a9ae101eb1 100644
--- a/src/tools/rust-analyzer/crates/edition/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/edition/Cargo.toml
@@ -1,6 +1,7 @@
 [package]
 name = "edition"
 version = "0.0.0"
+description = "Rust edition support crate for rust-analyzer."
 rust-version.workspace = true
 edition.workspace = true
 license.workspace = true
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 c0547bc3c8d..37e2a99e60f 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
@@ -1,6 +1,6 @@
 //! A higher level attributes based on TokenTree, with also some shortcuts.
 
-use std::{borrow::Cow, hash::Hash, ops, slice};
+use std::{borrow::Cow, hash::Hash, ops};
 
 use base_db::CrateId;
 use cfg::{CfgExpr, CfgOptions};
@@ -17,6 +17,7 @@ use syntax::{
     AstPtr,
 };
 use triomphe::Arc;
+use tt::iter::{TtElement, TtIter};
 
 use crate::{
     db::DefDatabase,
@@ -154,15 +155,15 @@ impl Attrs {
 
     pub fn has_doc_hidden(&self) -> bool {
         self.by_key(&sym::doc).tt_values().any(|tt| {
-            tt.delimiter.kind == DelimiterKind::Parenthesis &&
-                matches!(&*tt.token_trees, [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.sym == sym::hidden)
+            tt.top_subtree().delimiter.kind == DelimiterKind::Parenthesis &&
+                matches!(tt.token_trees().flat_tokens(), [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.sym == sym::hidden)
         })
     }
 
     pub fn has_doc_notable_trait(&self) -> bool {
         self.by_key(&sym::doc).tt_values().any(|tt| {
-            tt.delimiter.kind == DelimiterKind::Parenthesis &&
-                matches!(&*tt.token_trees, [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.sym == sym::notable_trait)
+            tt.top_subtree().delimiter.kind == DelimiterKind::Parenthesis &&
+                matches!(tt.token_trees().flat_tokens(), [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.sym == sym::notable_trait)
         })
     }
 
@@ -245,8 +246,8 @@ impl From<DocAtom> for DocExpr {
 }
 
 impl DocExpr {
-    fn parse<S>(tt: &tt::Subtree<S>) -> DocExpr {
-        next_doc_expr(&mut tt.token_trees.iter()).unwrap_or(DocExpr::Invalid)
+    fn parse<S: Copy>(tt: &tt::TopSubtree<S>) -> DocExpr {
+        next_doc_expr(tt.iter()).unwrap_or(DocExpr::Invalid)
     }
 
     pub fn aliases(&self) -> &[Symbol] {
@@ -260,32 +261,29 @@ impl DocExpr {
     }
 }
 
-fn next_doc_expr<S>(it: &mut slice::Iter<'_, tt::TokenTree<S>>) -> Option<DocExpr> {
+fn next_doc_expr<S: Copy>(mut it: TtIter<'_, S>) -> Option<DocExpr> {
     let name = match it.next() {
         None => return None,
-        Some(tt::TokenTree::Leaf(tt::Leaf::Ident(ident))) => ident.sym.clone(),
+        Some(TtElement::Leaf(tt::Leaf::Ident(ident))) => ident.sym.clone(),
         Some(_) => return Some(DocExpr::Invalid),
     };
 
     // Peek
-    let ret = match it.as_slice().first() {
-        Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) if punct.char == '=' => {
-            match it.as_slice().get(1) {
-                Some(tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
+    let ret = match it.peek() {
+        Some(TtElement::Leaf(tt::Leaf::Punct(punct))) if punct.char == '=' => {
+            it.next();
+            match it.next() {
+                Some(TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
                     symbol: text,
                     kind: tt::LitKind::Str,
                     ..
-                }))) => {
-                    it.next();
-                    it.next();
-                    DocAtom::KeyValue { key: name, value: text.clone() }.into()
-                }
+                }))) => DocAtom::KeyValue { key: name, value: text.clone() }.into(),
                 _ => return Some(DocExpr::Invalid),
             }
         }
-        Some(tt::TokenTree::Subtree(subtree)) => {
+        Some(TtElement::Subtree(_, subtree_iter)) => {
             it.next();
-            let subs = parse_comma_sep(subtree);
+            let subs = parse_comma_sep(subtree_iter);
             match &name {
                 s if *s == sym::alias => DocExpr::Alias(subs),
                 _ => DocExpr::Invalid,
@@ -293,29 +291,17 @@ fn next_doc_expr<S>(it: &mut slice::Iter<'_, tt::TokenTree<S>>) -> Option<DocExp
         }
         _ => DocAtom::Flag(name).into(),
     };
-
-    // Eat comma separator
-    if let Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) = it.as_slice().first() {
-        if punct.char == ',' {
-            it.next();
-        }
-    }
     Some(ret)
 }
 
-fn parse_comma_sep<S>(subtree: &tt::Subtree<S>) -> Vec<Symbol> {
-    subtree
-        .token_trees
-        .iter()
-        .filter_map(|tt| match tt {
-            tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
-                kind: tt::LitKind::Str,
-                symbol,
-                ..
-            })) => Some(symbol.clone()),
-            _ => None,
-        })
-        .collect()
+fn parse_comma_sep<S>(iter: TtIter<'_, S>) -> Vec<Symbol> {
+    iter.filter_map(|tt| match tt {
+        TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
+            kind: tt::LitKind::Str, symbol, ..
+        })) => Some(symbol.clone()),
+        _ => None,
+    })
+    .collect()
 }
 
 impl AttrsWithOwner {
@@ -563,7 +549,7 @@ pub struct AttrQuery<'attr> {
 }
 
 impl<'attr> AttrQuery<'attr> {
-    pub fn tt_values(self) -> impl Iterator<Item = &'attr crate::tt::Subtree> {
+    pub fn tt_values(self) -> impl Iterator<Item = &'attr crate::tt::TopSubtree> {
         self.attrs().filter_map(|attr| attr.token_tree_value())
     }
 
@@ -585,7 +571,7 @@ impl<'attr> AttrQuery<'attr> {
 
     pub fn attrs(self) -> impl Iterator<Item = &'attr Attr> + Clone {
         let key = self.key;
-        self.attrs.iter().filter(move |attr| attr.path.as_ident().map_or(false, |s| *s == *key))
+        self.attrs.iter().filter(move |attr| attr.path.as_ident().is_some_and(|s| *s == *key))
     }
 
     /// Find string value for a specific key inside token tree
@@ -596,12 +582,12 @@ impl<'attr> AttrQuery<'attr> {
     /// ```
     pub fn find_string_value_in_tt(self, key: &'attr Symbol) -> Option<&'attr str> {
         self.tt_values().find_map(|tt| {
-            let name = tt.token_trees.iter()
-                .skip_while(|tt| !matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { sym, ..} )) if *sym == *key))
+            let name = tt.iter()
+                .skip_while(|tt| !matches!(tt, TtElement::Leaf(tt::Leaf::Ident(tt::Ident { sym, ..} )) if *sym == *key))
                 .nth(2);
 
             match name {
-                Some(tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal{  symbol: text, kind: tt::LitKind::Str | tt::LitKind::StrRaw(_) , ..}))) => Some(text.as_str()),
+                Some(TtElement::Leaf(tt::Leaf::Literal(tt::Literal{  symbol: text, kind: tt::LitKind::Str | tt::LitKind::StrRaw(_) , ..}))) => Some(text.as_str()),
                 _ => None
             }
         })
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
index eed9f9468fd..10b84d041bd 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
@@ -2216,11 +2216,11 @@ impl ExprCollector<'_> {
         };
         // This needs to match `Flag` in library/core/src/fmt/rt.rs.
         let flags: u32 = ((sign == Some(FormatSign::Plus)) as u32)
-            | ((sign == Some(FormatSign::Minus)) as u32) << 1
-            | (alternate as u32) << 2
-            | (zero_pad as u32) << 3
-            | ((debug_hex == Some(FormatDebugHex::Lower)) as u32) << 4
-            | ((debug_hex == Some(FormatDebugHex::Upper)) as u32) << 5;
+            | (((sign == Some(FormatSign::Minus)) as u32) << 1)
+            | ((alternate as u32) << 2)
+            | ((zero_pad as u32) << 3)
+            | (((debug_hex == Some(FormatDebugHex::Lower)) as u32) << 4)
+            | (((debug_hex == Some(FormatDebugHex::Upper)) as u32) << 5);
         let flags = self.alloc_expr_desugared(Expr::Literal(Literal::Uint(
             flags as u128,
             Some(BuiltinUint::U32),
@@ -2468,7 +2468,7 @@ impl ExprCollector<'_> {
 
 fn comma_follows_token(t: Option<syntax::SyntaxToken>) -> bool {
     (|| syntax::algo::skip_trivia_token(t?.next_token()?, syntax::Direction::Next))()
-        .map_or(false, |it| it.kind() == syntax::T![,])
+        .is_some_and(|it| it.kind() == syntax::T![,])
 }
 
 #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs
index 13ba4db6064..7e15a9f2d61 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/tests.rs
@@ -52,6 +52,7 @@ fn your_stack_belongs_to_me() {
     cov_mark::check!(your_stack_belongs_to_me);
     lower(
         r#"
+#![recursion_limit = "32"]
 macro_rules! n_nuple {
     ($e:tt) => ();
     ($($rest:tt)*) => {{
@@ -68,6 +69,7 @@ fn your_stack_belongs_to_me2() {
     cov_mark::check!(overflow_but_not_me);
     lower(
         r#"
+#![recursion_limit = "32"]
 macro_rules! foo {
     () => {{ foo!(); foo!(); }}
 }
@@ -78,8 +80,6 @@ fn main() { foo!(); }
 
 #[test]
 fn recursion_limit() {
-    cov_mark::check!(your_stack_belongs_to_me);
-
     lower(
         r#"
 #![recursion_limit = "2"]
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 15dd6aba311..d85bc9a4320 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
@@ -11,6 +11,7 @@ use la_arena::{Idx, RawIdx};
 use smallvec::SmallVec;
 use syntax::{ast, Parse};
 use triomphe::Arc;
+use tt::iter::TtElement;
 
 use crate::{
     db::DefDatabase,
@@ -156,20 +157,21 @@ impl FunctionData {
     }
 }
 
-fn parse_rustc_legacy_const_generics(tt: &crate::tt::Subtree) -> Box<[u32]> {
+fn parse_rustc_legacy_const_generics(tt: &crate::tt::TopSubtree) -> Box<[u32]> {
     let mut indices = Vec::new();
-    for args in tt.token_trees.chunks(2) {
-        match &args[0] {
-            tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => match lit.symbol.as_str().parse() {
+    let mut iter = tt.iter();
+    while let (Some(first), second) = (iter.next(), iter.next()) {
+        match first {
+            TtElement::Leaf(tt::Leaf::Literal(lit)) => match lit.symbol.as_str().parse() {
                 Ok(index) => indices.push(index),
                 Err(_) => break,
             },
             _ => break,
         }
 
-        if let Some(comma) = args.get(1) {
+        if let Some(comma) = second {
             match comma {
-                tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if punct.char == ',' => {}
+                TtElement::Leaf(tt::Leaf::Punct(punct)) if punct.char == ',' => {}
                 _ => break,
             }
         }
@@ -227,20 +229,24 @@ impl TypeAliasData {
     }
 }
 
+bitflags::bitflags! {
+    #[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
+    pub struct TraitFlags: u8 {
+        const IS_AUTO = 1 << 0;
+        const IS_UNSAFE = 1 << 1;
+        const IS_FUNDAMENTAL = 1 << 2;
+        const RUSTC_HAS_INCOHERENT_INHERENT_IMPLS = 1 << 3;
+        const SKIP_ARRAY_DURING_METHOD_DISPATCH = 1 << 4;
+        const SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH = 1 << 5;
+    }
+}
+
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub struct TraitData {
     pub name: Name,
     pub items: Vec<(Name, AssocItemId)>,
-    pub is_auto: bool,
-    pub is_unsafe: bool,
-    pub rustc_has_incoherent_inherent_impls: bool,
-    pub skip_array_during_method_dispatch: bool,
-    pub skip_boxed_slice_during_method_dispatch: bool,
-    pub fundamental: bool,
+    pub flags: TraitFlags,
     pub visibility: RawVisibility,
-    /// Whether the trait has `#[rust_skip_array_during_method_dispatch]`. `hir_ty` will ignore
-    /// method calls to this trait's methods when the receiver is an array and the crate edition is
-    /// 2015 or 2018.
     // box it as the vec is usually empty anyways
     pub macro_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>,
 }
@@ -259,42 +265,50 @@ impl TraitData {
         let item_tree = tree_id.item_tree(db);
         let tr_def = &item_tree[tree_id.value];
         let name = tr_def.name.clone();
-        let is_auto = tr_def.is_auto;
-        let is_unsafe = tr_def.is_unsafe;
         let visibility = item_tree[tr_def.visibility].clone();
         let attrs = item_tree.attrs(db, module_id.krate(), ModItem::from(tree_id.value).into());
+
+        let mut flags = TraitFlags::empty();
+
+        if tr_def.is_auto {
+            flags |= TraitFlags::IS_AUTO;
+        }
+        if tr_def.is_unsafe {
+            flags |= TraitFlags::IS_UNSAFE;
+        }
+        if attrs.by_key(&sym::fundamental).exists() {
+            flags |= TraitFlags::IS_FUNDAMENTAL;
+        }
+        if attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists() {
+            flags |= TraitFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS;
+        }
+
         let mut skip_array_during_method_dispatch =
             attrs.by_key(&sym::rustc_skip_array_during_method_dispatch).exists();
         let mut skip_boxed_slice_during_method_dispatch = false;
         for tt in attrs.by_key(&sym::rustc_skip_during_method_dispatch).tt_values() {
-            for tt in tt.token_trees.iter() {
-                if let crate::tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) = tt {
+            for tt in tt.iter() {
+                if let tt::iter::TtElement::Leaf(tt::Leaf::Ident(ident)) = tt {
                     skip_array_during_method_dispatch |= ident.sym == sym::array;
                     skip_boxed_slice_during_method_dispatch |= ident.sym == sym::boxed_slice;
                 }
             }
         }
-        let rustc_has_incoherent_inherent_impls =
-            attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists();
-        let fundamental = attrs.by_key(&sym::fundamental).exists();
+
+        if skip_array_during_method_dispatch {
+            flags |= TraitFlags::SKIP_ARRAY_DURING_METHOD_DISPATCH;
+        }
+        if skip_boxed_slice_during_method_dispatch {
+            flags |= TraitFlags::SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH;
+        }
+
         let mut collector =
             AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr));
         collector.collect(&item_tree, tree_id.tree_id(), &tr_def.items);
         let (items, macro_calls, diagnostics) = collector.finish();
 
         (
-            Arc::new(TraitData {
-                name,
-                macro_calls,
-                items,
-                is_auto,
-                is_unsafe,
-                visibility,
-                skip_array_during_method_dispatch,
-                skip_boxed_slice_during_method_dispatch,
-                rustc_has_incoherent_inherent_impls,
-                fundamental,
-            }),
+            Arc::new(TraitData { name, macro_calls, items, visibility, flags }),
             DefDiagnostics::new(diagnostics),
         )
     }
@@ -421,7 +435,7 @@ impl Macro2Data {
             .by_key(&sym::rustc_builtin_macro)
             .tt_values()
             .next()
-            .and_then(|attr| parse_macro_name_and_helper_attrs(&attr.token_trees))
+            .and_then(parse_macro_name_and_helper_attrs)
             .map(|(_, helpers)| helpers);
 
         Arc::new(Macro2Data {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs
index 068ebb3b7e9..8fc19854033 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs
@@ -10,6 +10,7 @@ use intern::sym;
 use la_arena::Arena;
 use rustc_abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions};
 use triomphe::Arc;
+use tt::iter::TtElement;
 
 use crate::{
     builtin_type::{BuiltinInt, BuiltinUint},
@@ -20,7 +21,7 @@ use crate::{
     },
     lang_item::LangItem,
     nameres::diagnostics::{DefDiagnostic, DefDiagnostics},
-    tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree},
+    tt::{Delimiter, DelimiterKind, Leaf, TopSubtree},
     type_ref::{TypeRefId, TypesMap},
     visibility::RawVisibility,
     EnumId, EnumVariantId, LocalFieldId, LocalModuleId, Lookup, StructId, UnionId, VariantId,
@@ -95,8 +96,8 @@ fn repr_from_value(
     item_tree.attrs(db, krate, of).by_key(&sym::repr).tt_values().find_map(parse_repr_tt)
 }
 
-fn parse_repr_tt(tt: &Subtree) -> Option<ReprOptions> {
-    match tt.delimiter {
+fn parse_repr_tt(tt: &TopSubtree) -> Option<ReprOptions> {
+    match tt.top_subtree().delimiter {
         Delimiter { kind: DelimiterKind::Parenthesis, .. } => {}
         _ => return None,
     }
@@ -106,14 +107,14 @@ fn parse_repr_tt(tt: &Subtree) -> Option<ReprOptions> {
     let mut max_align: Option<Align> = None;
     let mut min_pack: Option<Align> = None;
 
-    let mut tts = tt.token_trees.iter().peekable();
+    let mut tts = tt.iter();
     while let Some(tt) = tts.next() {
-        if let TokenTree::Leaf(Leaf::Ident(ident)) = tt {
+        if let TtElement::Leaf(Leaf::Ident(ident)) = tt {
             flags.insert(match &ident.sym {
                 s if *s == sym::packed => {
-                    let pack = if let Some(TokenTree::Subtree(tt)) = tts.peek() {
+                    let pack = if let Some(TtElement::Subtree(_, mut tt_iter)) = tts.peek() {
                         tts.next();
-                        if let Some(TokenTree::Leaf(Leaf::Literal(lit))) = tt.token_trees.first() {
+                        if let Some(TtElement::Leaf(Leaf::Literal(lit))) = tt_iter.next() {
                             lit.symbol.as_str().parse().unwrap_or_default()
                         } else {
                             0
@@ -127,9 +128,9 @@ fn parse_repr_tt(tt: &Subtree) -> Option<ReprOptions> {
                     ReprFlags::empty()
                 }
                 s if *s == sym::align => {
-                    if let Some(TokenTree::Subtree(tt)) = tts.peek() {
+                    if let Some(TtElement::Subtree(_, mut tt_iter)) = tts.peek() {
                         tts.next();
-                        if let Some(TokenTree::Leaf(Leaf::Literal(lit))) = tt.token_trees.first() {
+                        if let Some(TtElement::Leaf(Leaf::Literal(lit))) = tt_iter.next() {
                             if let Ok(align) = lit.symbol.as_str().parse() {
                                 let align = Align::from_bytes(align).ok();
                                 max_align = max_align.max(align);
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs
index d7e83ce33e8..bf6cc1dcade 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs
@@ -21,6 +21,7 @@ use crate::{
     item_tree::{AttrOwner, ItemTree, ItemTreeSourceMaps},
     lang_item::{self, LangItem, LangItemTarget, LangItems},
     nameres::{diagnostics::DefDiagnostics, DefMap},
+    tt,
     type_ref::TypesSourceMap,
     visibility::{self, Visibility},
     AttrDefId, BlockId, BlockLoc, ConstBlockId, ConstBlockLoc, ConstId, ConstLoc, DefWithBodyId,
@@ -294,14 +295,14 @@ fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: CrateId) -> bool {
         // This is a `cfg_attr`; check if it could possibly expand to `no_std`.
         // Syntax is: `#[cfg_attr(condition(cfg, style), attr0, attr1, <...>)]`
         let tt = match attr.token_tree_value() {
-            Some(tt) => &tt.token_trees,
+            Some(tt) => tt.token_trees(),
             None => continue,
         };
 
         let segments =
-            tt.split(|tt| matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ','));
+            tt.split(|tt| matches!(tt, tt::TtElement::Leaf(tt::Leaf::Punct(p)) if p.char == ','));
         for output in segments.skip(1) {
-            match output {
+            match output.flat_tokens() {
                 [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.sym == sym::no_std => {
                     return true
                 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs
index 22005695af6..0f73595347b 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/dyn_map.rs
@@ -90,7 +90,7 @@ pub mod keys {
             map.map.get::<FxHashMap<AstPtr<AST>, ID>>()?.get(key)
         }
         fn is_empty(map: &DynMap) -> bool {
-            map.map.get::<FxHashMap<AstPtr<AST>, ID>>().map_or(true, |it| it.is_empty())
+            map.map.get::<FxHashMap<AstPtr<AST>, ID>>().is_none_or(|it| it.is_empty())
         }
     }
 }
@@ -141,7 +141,7 @@ impl<K: Hash + Eq + 'static, V: 'static> Policy for (K, V) {
         map.map.get::<FxHashMap<K, V>>()?.get(key)
     }
     fn is_empty(map: &DynMap) -> bool {
-        map.map.get::<FxHashMap<K, V>>().map_or(true, |it| it.is_empty())
+        map.map.get::<FxHashMap<K, V>>().is_none_or(|it| it.is_empty())
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs
index 163211fea52..c31d3221328 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs
@@ -2,7 +2,7 @@
 
 use expect_test::expect;
 
-use crate::macro_expansion_tests::check;
+use crate::macro_expansion_tests::{check, check_errors};
 
 #[test]
 fn test_copy_expand_simple() {
@@ -16,7 +16,7 @@ struct Foo;
 #[derive(Copy)]
 struct Foo;
 
-impl < > $crate::marker::Copy for Foo< > where {}"#]],
+impl <> $crate::marker::Copy for Foo< > where {}"#]],
     );
 }
 
@@ -40,7 +40,7 @@ macro Copy {}
 #[derive(Copy)]
 struct Foo;
 
-impl < > $crate::marker::Copy for Foo< > where {}"#]],
+impl <> $crate::marker::Copy for Foo< > where {}"#]],
     );
 }
 
@@ -225,14 +225,14 @@ enum Bar {
     Bar,
 }
 
-impl < > $crate::default::Default for Foo< > where {
+impl <> $crate::default::Default for Foo< > where {
     fn default() -> Self {
         Foo {
             field1: $crate::default::Default::default(), field2: $crate::default::Default::default(),
         }
     }
 }
-impl < > $crate::default::Default for Bar< > where {
+impl <> $crate::default::Default for Bar< > where {
     fn default() -> Self {
         Bar::Bar
     }
@@ -260,7 +260,7 @@ enum Command {
     Jump,
 }
 
-impl < > $crate::cmp::PartialEq for Command< > where {
+impl <> $crate::cmp::PartialEq for Command< > where {
     fn eq(&self , other: &Self ) -> bool {
         match (self , other) {
             (Command::Move {
@@ -273,7 +273,7 @@ impl < > $crate::cmp::PartialEq for Command< > where {
         }
     }
 }
-impl < > $crate::cmp::Eq for Command< > where {}"#]],
+impl <> $crate::cmp::Eq for Command< > where {}"#]],
     );
 }
 
@@ -298,7 +298,7 @@ enum Command {
     Jump,
 }
 
-impl < > $crate::cmp::PartialEq for Command< > where {
+impl <> $crate::cmp::PartialEq for Command< > where {
     fn eq(&self , other: &Self ) -> bool {
         match (self , other) {
             (Command::Move {
@@ -311,7 +311,7 @@ impl < > $crate::cmp::PartialEq for Command< > where {
         }
     }
 }
-impl < > $crate::cmp::Eq for Command< > where {}"#]],
+impl <> $crate::cmp::Eq for Command< > where {}"#]],
     );
 }
 
@@ -335,7 +335,7 @@ enum Command {
     Jump,
 }
 
-impl < > $crate::cmp::PartialOrd for Command< > where {
+impl <> $crate::cmp::PartialOrd for Command< > where {
     fn partial_cmp(&self , other: &Self ) -> $crate::option::Option::Option<$crate::cmp::Ordering> {
         match $crate::intrinsics::discriminant_value(self ).partial_cmp(&$crate::intrinsics::discriminant_value(other)) {
             $crate::option::Option::Some($crate::cmp::Ordering::Equal)=> {
@@ -370,7 +370,7 @@ impl < > $crate::cmp::PartialOrd for Command< > where {
         }
     }
 }
-impl < > $crate::cmp::Ord for Command< > where {
+impl <> $crate::cmp::Ord for Command< > where {
     fn cmp(&self , other: &Self ) -> $crate::cmp::Ordering {
         match $crate::intrinsics::discriminant_value(self ).cmp(&$crate::intrinsics::discriminant_value(other)) {
             $crate::cmp::Ordering::Equal=> {
@@ -432,7 +432,7 @@ struct Foo {
     z: (i32, u64),
 }
 
-impl < > $crate::hash::Hash for Foo< > where {
+impl <> $crate::hash::Hash for Foo< > where {
     fn hash<H: $crate::hash::Hasher>(&self , ra_expand_state: &mut H) {
         match self {
             Foo {
@@ -470,7 +470,7 @@ enum Command {
     Jump,
 }
 
-impl < > $crate::hash::Hash for Command< > where {
+impl <> $crate::hash::Hash for Command< > where {
     fn hash<H: $crate::hash::Hasher>(&self , ra_expand_state: &mut H) {
         $crate::mem::discriminant(self ).hash(ra_expand_state);
         match self {
@@ -516,7 +516,7 @@ enum Command {
     Jump,
 }
 
-impl < > $crate::fmt::Debug for Command< > where {
+impl <> $crate::fmt::Debug for Command< > where {
     fn fmt(&self , f: &mut $crate::fmt::Formatter) -> $crate::fmt::Result {
         match self {
             Command::Move {
@@ -578,7 +578,7 @@ enum HideAndShowEnum {
     }
 }
 
-impl < > $crate::fmt::Debug for HideAndShow< > where {
+impl <> $crate::fmt::Debug for HideAndShow< > where {
     fn fmt(&self , f: &mut $crate::fmt::Formatter) -> $crate::fmt::Result {
         match self {
             HideAndShow {
@@ -588,7 +588,7 @@ impl < > $crate::fmt::Debug for HideAndShow< > where {
         }
     }
 }
-impl < > $crate::fmt::Debug for HideAndShowEnum< > where {
+impl <> $crate::fmt::Debug for HideAndShowEnum< > where {
     fn fmt(&self , f: &mut $crate::fmt::Formatter) -> $crate::fmt::Result {
         match self {
             HideAndShowEnum::AlwaysShow {
@@ -640,17 +640,109 @@ enum Bar {
     Bar,
 }
 
-impl < > $crate::default::Default for Foo< > where {
+impl <> $crate::default::Default for Foo< > where {
     fn default() -> Self {
         Foo {
             field1: $crate::default::Default::default(), field4: $crate::default::Default::default(),
         }
     }
 }
-impl < > $crate::default::Default for Bar< > where {
+impl <> $crate::default::Default for Bar< > where {
     fn default() -> Self {
         Bar::Bar
     }
 }"##]],
     );
 }
+
+#[test]
+fn coerce_pointee_expansion() {
+    check(
+        r#"
+//- minicore: coerce_pointee
+
+use core::marker::CoercePointee;
+
+pub trait Trait<T: ?Sized> {}
+
+#[derive(CoercePointee)]
+#[repr(transparent)]
+pub struct Foo<'a, T: ?Sized + Trait<U>, #[pointee] U: ?Sized, const N: u32>(T)
+where
+    U: Trait<U> + ToString;"#,
+        expect![[r#"
+
+use core::marker::CoercePointee;
+
+pub trait Trait<T: ?Sized> {}
+
+#[derive(CoercePointee)]
+#[repr(transparent)]
+pub struct Foo<'a, T: ?Sized + Trait<U>, #[pointee] U: ?Sized, const N: u32>(T)
+where
+    U: Trait<U> + ToString;
+impl <T, U, const N: u32, __S> $crate::ops::DispatchFromDyn<Foo<'a, T, __S, N>> for Foo<T, U, N, > where U: Trait<U> +ToString, T: Trait<__S>, __S: ?Sized, __S: Trait<__S> +ToString, U: ::core::marker::Unsize<__S>, T:?Sized+Trait<U>, U:?Sized, {}
+impl <T, U, const N: u32, __S> $crate::ops::CoerceUnsized<Foo<'a, T, __S, N>> for Foo<T, U, N, > where U: Trait<U> +ToString, T: Trait<__S>, __S: ?Sized, __S: Trait<__S> +ToString, U: ::core::marker::Unsize<__S>, T:?Sized+Trait<U>, U:?Sized, {}"#]],
+    );
+}
+
+#[test]
+fn coerce_pointee_errors() {
+    check_errors(
+        r#"
+//- minicore: coerce_pointee
+
+use core::marker::CoercePointee;
+
+#[derive(CoercePointee)]
+enum Enum {}
+
+#[derive(CoercePointee)]
+struct Struct1;
+
+#[derive(CoercePointee)]
+struct Struct2();
+
+#[derive(CoercePointee)]
+struct Struct3 {}
+
+#[derive(CoercePointee)]
+struct Struct4<T: ?Sized>(T);
+
+#[derive(CoercePointee)]
+#[repr(transparent)]
+struct Struct5(i32);
+
+#[derive(CoercePointee)]
+#[repr(transparent)]
+struct Struct6<#[pointee] T: ?Sized, #[pointee] U: ?Sized>(T, U);
+
+#[derive(CoercePointee)]
+#[repr(transparent)]
+struct Struct7<T: ?Sized, U: ?Sized>(T, U);
+
+#[derive(CoercePointee)]
+#[repr(transparent)]
+struct Struct8<#[pointee] T, U: ?Sized>(T);
+
+#[derive(CoercePointee)]
+#[repr(transparent)]
+struct Struct9<T>(T);
+
+#[derive(CoercePointee)]
+#[repr(transparent)]
+struct Struct9<#[pointee] T, U>(T) where T: ?Sized;
+"#,
+        expect![[r#"
+            35..72: `CoercePointee` can only be derived on `struct`s
+            74..114: `CoercePointee` can only be derived on `struct`s with at least one field
+            116..158: `CoercePointee` can only be derived on `struct`s with at least one field
+            160..202: `CoercePointee` can only be derived on `struct`s with at least one field
+            204..258: `CoercePointee` can only be derived on `struct`s with `#[repr(transparent)]`
+            260..326: `CoercePointee` can only be derived on `struct`s that are generic over at least one type
+            328..439: only one type parameter can be marked as `#[pointee]` when deriving `CoercePointee` traits
+            441..530: exactly one generic type parameter must be marked as `#[pointee]` to derive `CoercePointee` traits
+            532..621: `derive(CoercePointee)` requires `T` to be marked `?Sized`
+            623..690: `derive(CoercePointee)` requires `T` to be marked `?Sized`"#]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs
index 0475e40c5b2..5b9ffdf37be 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs
@@ -16,14 +16,16 @@ mod proc_macros;
 
 use std::{iter, ops::Range, sync};
 
+use base_db::SourceDatabase;
 use expect_test::Expect;
 use hir_expand::{
     db::ExpandDatabase,
     proc_macro::{ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroKind},
     span_map::SpanMapRef,
-    InFile, MacroFileId, MacroFileIdExt,
+    InFile, MacroCallKind, MacroFileId, MacroFileIdExt,
 };
 use intern::Symbol;
+use itertools::Itertools;
 use span::{Edition, Span};
 use stdx::{format_to, format_to_acc};
 use syntax::{
@@ -40,11 +42,41 @@ use crate::{
     resolver::HasResolver,
     src::HasSource,
     test_db::TestDB,
-    tt::Subtree,
+    tt::TopSubtree,
     AdtId, AsMacroCall, Lookup, ModuleDefId,
 };
 
 #[track_caller]
+fn check_errors(ra_fixture: &str, expect: Expect) {
+    let db = TestDB::with_files(ra_fixture);
+    let krate = db.fetch_test_crate();
+    let def_map = db.crate_def_map(krate);
+    let errors = def_map
+        .modules()
+        .flat_map(|module| module.1.scope.all_macro_calls())
+        .filter_map(|macro_call| {
+            let errors = db.parse_macro_expansion_error(macro_call)?;
+            let errors = errors.err.as_ref()?.render_to_string(&db);
+            let macro_loc = db.lookup_intern_macro_call(macro_call);
+            let ast_id = match macro_loc.kind {
+                MacroCallKind::FnLike { ast_id, .. } => ast_id.map(|it| it.erase()),
+                MacroCallKind::Derive { ast_id, .. } => ast_id.map(|it| it.erase()),
+                MacroCallKind::Attr { ast_id, .. } => ast_id.map(|it| it.erase()),
+            };
+            let ast = db
+                .parse(ast_id.file_id.file_id().expect("macros inside macros are not supported"))
+                .syntax_node();
+            let ast_id_map = db.ast_id_map(ast_id.file_id);
+            let node = ast_id_map.get_erased(ast_id.value).to_node(&ast);
+            Some((node.text_range(), errors))
+        })
+        .sorted_unstable_by_key(|(range, _)| range.start())
+        .format_with("\n", |(range, err), format| format(&format_args!("{range:?}: {err}")))
+        .to_string();
+    expect.assert_eq(&errors);
+}
+
+#[track_caller]
 fn check(ra_fixture: &str, mut expect: Expect) {
     let extra_proc_macros = vec![(
         r#"
@@ -245,7 +277,9 @@ fn pretty_print_macro_expansion(
     let mut res = String::new();
     let mut prev_kind = EOF;
     let mut indent_level = 0;
-    for token in iter::successors(expn.first_token(), |t| t.next_token()) {
+    for token in iter::successors(expn.first_token(), |t| t.next_token())
+        .take_while(|token| token.text_range().start() < expn.text_range().end())
+    {
         let curr_kind = token.kind();
         let space = match (prev_kind, curr_kind) {
             _ if prev_kind.is_trivia() || curr_kind.is_trivia() => "",
@@ -313,14 +347,14 @@ struct IdentityWhenValidProcMacroExpander;
 impl ProcMacroExpander for IdentityWhenValidProcMacroExpander {
     fn expand(
         &self,
-        subtree: &Subtree,
-        _: Option<&Subtree>,
+        subtree: &TopSubtree,
+        _: Option<&TopSubtree>,
         _: &base_db::Env,
         _: Span,
         _: Span,
         _: Span,
         _: Option<String>,
-    ) -> Result<Subtree, ProcMacroExpansionError> {
+    ) -> Result<TopSubtree, ProcMacroExpansionError> {
         let (parse, _) = syntax_bridge::token_tree_to_syntax_node(
             subtree,
             syntax_bridge::TopEntryPoint::MacroItems,
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 9bd7d38f0a6..39d383f0159 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
@@ -85,6 +85,8 @@ use crate::{
     FxIndexMap, LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId,
 };
 
+pub use self::path_resolution::ResolvePathResultPrefixInfo;
+
 const PREDEFINED_TOOLS: &[SmolStr] = &[
     SmolStr::new_static("clippy"),
     SmolStr::new_static("rustfmt"),
@@ -615,13 +617,15 @@ impl DefMap {
         (res.resolved_def, res.segment_index)
     }
 
+    /// The first `Option<usize>` points at the `Enum` segment in case of `Enum::Variant`, the second
+    /// points at the unresolved segments.
     pub(crate) fn resolve_path_locally(
         &self,
         db: &dyn DefDatabase,
         original_module: LocalModuleId,
         path: &ModPath,
         shadow: BuiltinShadowMode,
-    ) -> (PerNs, Option<usize>) {
+    ) -> (PerNs, Option<usize>, ResolvePathResultPrefixInfo) {
         let res = self.resolve_path_fp_with_macro_single(
             db,
             ResolveMode::Other,
@@ -630,7 +634,7 @@ impl DefMap {
             shadow,
             None, // Currently this function isn't used for macro resolution.
         );
-        (res.resolved_def, res.segment_index)
+        (res.resolved_def, res.segment_index, res.prefix_info)
     }
 
     /// Ascends the `DefMap` hierarchy and calls `f` with every `DefMap` and containing module.
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 747860fd8e1..d1f6ed023c2 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
@@ -110,8 +110,8 @@ pub(super) fn attr_macro_as_call_id(
 ) -> MacroCallId {
     let arg = match macro_attr.input.as_deref() {
         Some(AttrInput::TokenTree(tt)) => {
-            let mut tt = tt.as_ref().clone();
-            tt.delimiter.kind = tt::DelimiterKind::Invisible;
+            let mut tt = tt.clone();
+            tt.top_subtree_delimiter_mut().kind = tt::DelimiterKind::Invisible;
             Some(tt)
         }
 
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 f391cc41c18..8beeda82bca 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
@@ -353,7 +353,7 @@ impl DefCollector<'_> {
         let is_cfg_enabled = item_tree
             .top_level_attrs(self.db, self.def_map.krate)
             .cfg()
-            .map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false));
+            .is_none_or(|cfg| self.cfg_options.check(&cfg) != Some(false));
         if is_cfg_enabled {
             self.inject_prelude();
 
@@ -797,7 +797,7 @@ impl DefCollector<'_> {
             return PartialResolvedImport::Unresolved;
         }
 
-        if res.from_differing_crate {
+        if res.prefix_info.differing_crate {
             return PartialResolvedImport::Resolved(
                 def.filter_visibility(|v| matches!(v, Visibility::Public)),
             );
@@ -1316,6 +1316,7 @@ impl DefCollector<'_> {
                     // being cfg'ed out).
                     // Ideally we will just expand them to nothing here. But we are only collecting macro calls,
                     // not expanding them, so we have no way to do that.
+                    // If you add an ignored attribute here, also add it to `Semantics::might_be_inside_macro_call()`.
                     if matches!(
                         def.kind,
                         MacroDefKind::BuiltInAttr(_, expander)
@@ -1451,13 +1452,7 @@ impl DefCollector<'_> {
         depth: usize,
         container: ItemContainerId,
     ) {
-        let recursion_limit = self.def_map.recursion_limit() as usize;
-        let recursion_limit = Limit::new(if cfg!(test) {
-            // Without this, `body::tests::your_stack_belongs_to_me` stack-overflows in debug
-            std::cmp::min(32, recursion_limit)
-        } else {
-            recursion_limit
-        });
+        let recursion_limit = Limit::new(self.def_map.recursion_limit() as usize);
         if recursion_limit.check(depth).is_err() {
             cov_mark::hit!(macro_expansion_overflow);
             tracing::warn!("macro expansion is too deep");
@@ -2220,8 +2215,8 @@ impl ModCollector<'_, '_> {
 
         let is_export = export_attr.exists();
         let local_inner = if is_export {
-            export_attr.tt_values().flat_map(|it| it.token_trees.iter()).any(|it| match it {
-                tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident.sym == sym::local_inner_macros,
+            export_attr.tt_values().flat_map(|it| it.iter()).any(|it| match it {
+                tt::TtElement::Leaf(tt::Leaf::Ident(ident)) => ident.sym == sym::local_inner_macros,
                 _ => false,
             })
         } else {
@@ -2240,7 +2235,7 @@ impl ModCollector<'_, '_> {
                 None => {
                     let explicit_name =
                         attrs.by_key(&sym::rustc_builtin_macro).tt_values().next().and_then(|tt| {
-                            match tt.token_trees.first() {
+                            match tt.token_trees().flat_tokens().first() {
                                 Some(tt::TokenTree::Leaf(tt::Leaf::Ident(name))) => Some(name),
                                 _ => None,
                             }
@@ -2310,9 +2305,7 @@ impl ModCollector<'_, '_> {
                     // NOTE: The item *may* have both `#[rustc_builtin_macro]` and `#[proc_macro_derive]`,
                     // in which case rustc ignores the helper attributes from the latter, but it
                     // "doesn't make sense in practice" (see rust-lang/rust#87027).
-                    if let Some((name, helpers)) =
-                        parse_macro_name_and_helper_attrs(&attr.token_trees)
-                    {
+                    if let Some((name, helpers)) = parse_macro_name_and_helper_attrs(attr) {
                         // NOTE: rustc overrides the name if the macro name if it's different from the
                         // macro name, but we assume it isn't as there's no such case yet. FIXME if
                         // the following assertion fails.
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 8eb195680d1..47c08d3d1dc 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
@@ -43,21 +43,33 @@ pub(super) struct ResolvePathResult {
     pub(super) resolved_def: PerNs,
     pub(super) segment_index: Option<usize>,
     pub(super) reached_fixedpoint: ReachedFixedPoint,
-    pub(super) from_differing_crate: bool,
+    pub(super) prefix_info: ResolvePathResultPrefixInfo,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
+pub struct ResolvePathResultPrefixInfo {
+    pub(crate) differing_crate: bool,
+    /// Path of the form `Enum::Variant` (and not `Variant` alone).
+    pub enum_variant: bool,
 }
 
 impl ResolvePathResult {
     fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult {
-        ResolvePathResult::new(PerNs::none(), reached_fixedpoint, None, false)
+        ResolvePathResult::new(
+            PerNs::none(),
+            reached_fixedpoint,
+            None,
+            ResolvePathResultPrefixInfo::default(),
+        )
     }
 
     fn new(
         resolved_def: PerNs,
         reached_fixedpoint: ReachedFixedPoint,
         segment_index: Option<usize>,
-        from_differing_crate: bool,
+        prefix_info: ResolvePathResultPrefixInfo,
     ) -> ResolvePathResult {
-        ResolvePathResult { resolved_def, segment_index, reached_fixedpoint, from_differing_crate }
+        ResolvePathResult { resolved_def, segment_index, reached_fixedpoint, prefix_info }
     }
 }
 
@@ -157,7 +169,8 @@ impl DefMap {
             if result.reached_fixedpoint == ReachedFixedPoint::No {
                 result.reached_fixedpoint = new.reached_fixedpoint;
             }
-            result.from_differing_crate |= new.from_differing_crate;
+            result.prefix_info.differing_crate |= new.prefix_info.differing_crate;
+            result.prefix_info.enum_variant |= new.prefix_info.enum_variant;
             result.segment_index = match (result.segment_index, new.segment_index) {
                 (Some(idx), None) => Some(idx),
                 (Some(old), Some(new)) => Some(old.max(new)),
@@ -403,14 +416,14 @@ impl DefMap {
 
     fn resolve_remaining_segments<'a>(
         &self,
-        segments: impl Iterator<Item = (usize, &'a Name)>,
+        mut segments: impl Iterator<Item = (usize, &'a Name)>,
         mut curr_per_ns: PerNs,
         path: &ModPath,
         db: &dyn DefDatabase,
         shadow: BuiltinShadowMode,
         original_module: LocalModuleId,
     ) -> ResolvePathResult {
-        for (i, segment) in segments {
+        while let Some((i, segment)) = segments.next() {
             let curr = match curr_per_ns.take_types_full() {
                 Some(r) => r,
                 None => {
@@ -437,13 +450,22 @@ impl DefMap {
                         // because `macro_use` and other preludes should be taken into account. At
                         // this point, we know we're resolving a multi-segment path so macro kind
                         // expectation is discarded.
-                        let (def, s) =
-                            defp_map.resolve_path(db, module.local_id, &path, shadow, None);
+                        let resolution = defp_map.resolve_path_fp_with_macro(
+                            db,
+                            ResolveMode::Other,
+                            module.local_id,
+                            &path,
+                            shadow,
+                            None,
+                        );
                         return ResolvePathResult::new(
-                            def,
+                            resolution.resolved_def,
                             ReachedFixedPoint::Yes,
-                            s.map(|s| s + i),
-                            true,
+                            resolution.segment_index.map(|s| s + i),
+                            ResolvePathResultPrefixInfo {
+                                differing_crate: true,
+                                enum_variant: resolution.prefix_info.enum_variant,
+                            },
                         );
                     }
 
@@ -488,17 +510,31 @@ impl DefMap {
                             ),
                         })
                     });
-                    match res {
-                        Some(res) => res,
-                        None => {
-                            return ResolvePathResult::new(
-                                PerNs::types(e.into(), curr.vis, curr.import),
-                                ReachedFixedPoint::Yes,
-                                Some(i),
-                                false,
-                            )
+                    // FIXME: Need to filter visibility here and below? Not sure.
+                    return match res {
+                        Some(res) => {
+                            if segments.next().is_some() {
+                                // Enum variants are in value namespace, segments left => no resolution.
+                                ResolvePathResult::empty(ReachedFixedPoint::No)
+                            } else {
+                                ResolvePathResult::new(
+                                    res,
+                                    ReachedFixedPoint::Yes,
+                                    None,
+                                    ResolvePathResultPrefixInfo {
+                                        enum_variant: true,
+                                        ..ResolvePathResultPrefixInfo::default()
+                                    },
+                                )
+                            }
                         }
-                    }
+                        None => ResolvePathResult::new(
+                            PerNs::types(e.into(), curr.vis, curr.import),
+                            ReachedFixedPoint::Yes,
+                            Some(i),
+                            ResolvePathResultPrefixInfo::default(),
+                        ),
+                    };
                 }
                 s => {
                     // could be an inherent method call in UFCS form
@@ -513,7 +549,7 @@ impl DefMap {
                         PerNs::types(s, curr.vis, curr.import),
                         ReachedFixedPoint::Yes,
                         Some(i),
-                        false,
+                        ResolvePathResultPrefixInfo::default(),
                     );
                 }
             };
@@ -522,7 +558,12 @@ impl DefMap {
                 .filter_visibility(|vis| vis.is_visible_from_def_map(db, self, original_module));
         }
 
-        ResolvePathResult::new(curr_per_ns, ReachedFixedPoint::Yes, None, false)
+        ResolvePathResult::new(
+            curr_per_ns,
+            ReachedFixedPoint::Yes,
+            None,
+            ResolvePathResultPrefixInfo::default(),
+        )
     }
 
     fn resolve_name_in_module(
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 fd0b52bc7d7..b93a1c87b43 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
@@ -4,7 +4,7 @@ use hir_expand::name::{AsName, Name};
 use intern::sym;
 
 use crate::attr::Attrs;
-use crate::tt::{Leaf, TokenTree};
+use crate::tt::{Leaf, TokenTree, TopSubtree, TtElement};
 
 #[derive(Debug, PartialEq, Eq)]
 pub struct ProcMacroDef {
@@ -38,7 +38,7 @@ impl Attrs {
             Some(ProcMacroDef { name: func_name.clone(), kind: ProcMacroKind::Attr })
         } else if self.by_key(&sym::proc_macro_derive).exists() {
             let derive = self.by_key(&sym::proc_macro_derive).tt_values().next()?;
-            let def = parse_macro_name_and_helper_attrs(&derive.token_trees)
+            let def = parse_macro_name_and_helper_attrs(derive)
                 .map(|(name, helpers)| ProcMacroDef { name, kind: ProcMacroKind::Derive { helpers } });
 
             if def.is_none() {
@@ -55,8 +55,8 @@ impl Attrs {
 // This fn is intended for `#[proc_macro_derive(..)]` and `#[rustc_builtin_macro(..)]`, which have
 // the same structure.
 #[rustfmt::skip]
-pub(crate) fn parse_macro_name_and_helper_attrs(tt: &[TokenTree]) -> Option<(Name, Box<[Name]>)> {
-    match tt {
+pub(crate) fn parse_macro_name_and_helper_attrs(tt: &TopSubtree) -> Option<(Name, Box<[Name]>)> {
+    match tt.token_trees().flat_tokens() {
         // `#[proc_macro_derive(Trait)]`
         // `#[rustc_builtin_macro(Trait)]`
         [TokenTree::Leaf(Leaf::Ident(trait_name))] => Some((trait_name.as_name(), Box::new([]))),
@@ -67,17 +67,18 @@ pub(crate) fn parse_macro_name_and_helper_attrs(tt: &[TokenTree]) -> Option<(Nam
             TokenTree::Leaf(Leaf::Ident(trait_name)),
             TokenTree::Leaf(Leaf::Punct(comma)),
             TokenTree::Leaf(Leaf::Ident(attributes)),
-            TokenTree::Subtree(helpers)
+            TokenTree::Subtree(_),
+            ..
         ] if comma.char == ',' && attributes.sym == sym::attributes =>
         {
+            let helpers = tt::TokenTreesView::new(&tt.token_trees().flat_tokens()[3..]).try_into_subtree()?;
             let helpers = helpers
-                .token_trees
                 .iter()
                 .filter(
-                    |tt| !matches!(tt, TokenTree::Leaf(Leaf::Punct(comma)) if comma.char == ','),
+                    |tt| !matches!(tt, TtElement::Leaf(Leaf::Punct(comma)) if comma.char == ','),
                 )
                 .map(|tt| match tt {
-                    TokenTree::Leaf(Leaf::Ident(helper)) => Some(helper.as_name()),
+                    TtElement::Leaf(Leaf::Ident(helper)) => Some(helper.as_name()),
                     _ => None,
                 })
                 .collect::<Option<Box<[_]>>>()?;
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/path.rs b/src/tools/rust-analyzer/crates/hir-def/src/path.rs
index 44e132061ad..e59c37104dd 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/path.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/path.rs
@@ -240,6 +240,7 @@ pub struct PathSegment<'a> {
     pub args_and_bindings: Option<&'a GenericArgs>,
 }
 
+#[derive(Debug, Clone, Copy)]
 pub struct PathSegments<'a> {
     segments: &'a [Name],
     generic_args: Option<&'a [Option<GenericArgs>]>,
@@ -259,6 +260,7 @@ impl<'a> PathSegments<'a> {
     pub fn last(&self) -> Option<PathSegment<'a>> {
         self.get(self.len().checked_sub(1)?)
     }
+
     pub fn get(&self, idx: usize) -> Option<PathSegment<'a>> {
         let res = PathSegment {
             name: self.segments.get(idx)?,
@@ -266,24 +268,37 @@ impl<'a> PathSegments<'a> {
         };
         Some(res)
     }
+
     pub fn skip(&self, len: usize) -> PathSegments<'a> {
         PathSegments {
             segments: self.segments.get(len..).unwrap_or(&[]),
             generic_args: self.generic_args.and_then(|it| it.get(len..)),
         }
     }
+
     pub fn take(&self, len: usize) -> PathSegments<'a> {
         PathSegments {
             segments: self.segments.get(..len).unwrap_or(self.segments),
             generic_args: self.generic_args.map(|it| it.get(..len).unwrap_or(it)),
         }
     }
+
     pub fn strip_last(&self) -> PathSegments<'a> {
         PathSegments {
             segments: self.segments.split_last().map_or(&[], |it| it.1),
             generic_args: self.generic_args.map(|it| it.split_last().map_or(&[][..], |it| it.1)),
         }
     }
+
+    pub fn strip_last_two(&self) -> PathSegments<'a> {
+        PathSegments {
+            segments: self.segments.get(..self.segments.len().saturating_sub(2)).unwrap_or(&[]),
+            generic_args: self
+                .generic_args
+                .map(|it| it.get(..it.len().saturating_sub(2)).unwrap_or(&[])),
+        }
+    }
+
     pub fn iter(&self) -> impl Iterator<Item = PathSegment<'a>> {
         self.segments
             .iter()
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 f4dfd42a30e..82da57a9bb2 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
@@ -21,7 +21,7 @@ use crate::{
     hir::{BindingId, ExprId, LabelId},
     item_scope::{BuiltinShadowMode, ImportId, ImportOrExternCrate, BUILTIN_SCOPE},
     lang_item::LangItemTarget,
-    nameres::{DefMap, MacroSubNs},
+    nameres::{DefMap, MacroSubNs, ResolvePathResultPrefixInfo},
     path::{ModPath, Path, PathKind},
     per_ns::PerNs,
     type_ref::{LifetimeRef, TypesMap},
@@ -263,25 +263,37 @@ impl Resolver {
         &self,
         db: &dyn DefDatabase,
         path: &Path,
-        mut hygiene_id: HygieneId,
+        hygiene_id: HygieneId,
     ) -> Option<ResolveValueResult> {
+        self.resolve_path_in_value_ns_with_prefix_info(db, path, hygiene_id).map(|(it, _)| it)
+    }
+
+    pub fn resolve_path_in_value_ns_with_prefix_info(
+        &self,
+        db: &dyn DefDatabase,
+        path: &Path,
+        mut hygiene_id: HygieneId,
+    ) -> Option<(ResolveValueResult, ResolvePathResultPrefixInfo)> {
         let path = match path {
             Path::BarePath(mod_path) => mod_path,
             Path::Normal(it) => it.mod_path(),
             Path::LangItem(l, None) => {
-                return Some(ResolveValueResult::ValueNs(
-                    match *l {
-                        LangItemTarget::Function(it) => ValueNs::FunctionId(it),
-                        LangItemTarget::Static(it) => ValueNs::StaticId(it),
-                        LangItemTarget::Struct(it) => ValueNs::StructId(it),
-                        LangItemTarget::EnumVariant(it) => ValueNs::EnumVariantId(it),
-                        LangItemTarget::Union(_)
-                        | LangItemTarget::ImplDef(_)
-                        | LangItemTarget::TypeAlias(_)
-                        | LangItemTarget::Trait(_)
-                        | LangItemTarget::EnumId(_) => return None,
-                    },
-                    None,
+                return Some((
+                    ResolveValueResult::ValueNs(
+                        match *l {
+                            LangItemTarget::Function(it) => ValueNs::FunctionId(it),
+                            LangItemTarget::Static(it) => ValueNs::StaticId(it),
+                            LangItemTarget::Struct(it) => ValueNs::StructId(it),
+                            LangItemTarget::EnumVariant(it) => ValueNs::EnumVariantId(it),
+                            LangItemTarget::Union(_)
+                            | LangItemTarget::ImplDef(_)
+                            | LangItemTarget::TypeAlias(_)
+                            | LangItemTarget::Trait(_)
+                            | LangItemTarget::EnumId(_) => return None,
+                        },
+                        None,
+                    ),
+                    ResolvePathResultPrefixInfo::default(),
                 ))
             }
             Path::LangItem(l, Some(_)) => {
@@ -296,7 +308,10 @@ impl Resolver {
                     | LangItemTarget::ImplDef(_)
                     | LangItemTarget::Static(_) => return None,
                 };
-                return Some(ResolveValueResult::Partial(type_ns, 1, None));
+                return Some((
+                    ResolveValueResult::Partial(type_ns, 1, None),
+                    ResolvePathResultPrefixInfo::default(),
+                ));
             }
         };
         let n_segments = path.segments().len();
@@ -326,9 +341,12 @@ impl Resolver {
                             });
 
                         if let Some(e) = entry {
-                            return Some(ResolveValueResult::ValueNs(
-                                ValueNs::LocalBinding(e.binding()),
-                                None,
+                            return Some((
+                                ResolveValueResult::ValueNs(
+                                    ValueNs::LocalBinding(e.binding()),
+                                    None,
+                                ),
+                                ResolvePathResultPrefixInfo::default(),
                             ));
                         }
                     }
@@ -350,14 +368,17 @@ impl Resolver {
                     Scope::GenericParams { params, def } => {
                         if let Some(id) = params.find_const_by_name(first_name, *def) {
                             let val = ValueNs::GenericParam(id);
-                            return Some(ResolveValueResult::ValueNs(val, None));
+                            return Some((
+                                ResolveValueResult::ValueNs(val, None),
+                                ResolvePathResultPrefixInfo::default(),
+                            ));
                         }
                     }
                     &Scope::ImplDefScope(impl_) => {
                         if *first_name == sym::Self_.clone() {
-                            return Some(ResolveValueResult::ValueNs(
-                                ValueNs::ImplSelf(impl_),
-                                None,
+                            return Some((
+                                ResolveValueResult::ValueNs(ValueNs::ImplSelf(impl_), None),
+                                ResolvePathResultPrefixInfo::default(),
                             ));
                         }
                     }
@@ -377,22 +398,27 @@ impl Resolver {
                     Scope::GenericParams { params, def } => {
                         if let Some(id) = params.find_type_by_name(first_name, *def) {
                             let ty = TypeNs::GenericParam(id);
-                            return Some(ResolveValueResult::Partial(ty, 1, None));
+                            return Some((
+                                ResolveValueResult::Partial(ty, 1, None),
+                                ResolvePathResultPrefixInfo::default(),
+                            ));
                         }
                     }
                     &Scope::ImplDefScope(impl_) => {
                         if *first_name == sym::Self_.clone() {
-                            return Some(ResolveValueResult::Partial(
-                                TypeNs::SelfType(impl_),
-                                1,
-                                None,
+                            return Some((
+                                ResolveValueResult::Partial(TypeNs::SelfType(impl_), 1, None),
+                                ResolvePathResultPrefixInfo::default(),
                             ));
                         }
                     }
                     Scope::AdtScope(adt) => {
                         if *first_name == sym::Self_.clone() {
                             let ty = TypeNs::AdtSelfType(*adt);
-                            return Some(ResolveValueResult::Partial(ty, 1, None));
+                            return Some((
+                                ResolveValueResult::Partial(ty, 1, None),
+                                ResolvePathResultPrefixInfo::default(),
+                            ));
                         }
                     }
                     Scope::BlockScope(m) => {
@@ -413,7 +439,10 @@ impl Resolver {
         // `use core::u16;`.
         if path.kind == PathKind::Plain && n_segments > 1 {
             if let Some(builtin) = BuiltinType::by_name(first_name) {
-                return Some(ResolveValueResult::Partial(TypeNs::BuiltinType(builtin), 1, None));
+                return Some((
+                    ResolveValueResult::Partial(TypeNs::BuiltinType(builtin), 1, None),
+                    ResolvePathResultPrefixInfo::default(),
+                ));
             }
         }
 
@@ -924,15 +953,15 @@ impl ModuleItemMap {
         &self,
         db: &dyn DefDatabase,
         path: &ModPath,
-    ) -> Option<ResolveValueResult> {
-        let (module_def, idx) =
+    ) -> Option<(ResolveValueResult, ResolvePathResultPrefixInfo)> {
+        let (module_def, unresolved_idx, prefix_info) =
             self.def_map.resolve_path_locally(db, self.module_id, path, BuiltinShadowMode::Other);
-        match idx {
+        match unresolved_idx {
             None => {
                 let (value, import) = to_value_ns(module_def)?;
-                Some(ResolveValueResult::ValueNs(value, import))
+                Some((ResolveValueResult::ValueNs(value, import), prefix_info))
             }
-            Some(idx) => {
+            Some(unresolved_idx) => {
                 let def = module_def.take_types_full()?;
                 let ty = match def.def {
                     ModuleDefId::AdtId(it) => TypeNs::AdtId(it),
@@ -948,7 +977,7 @@ impl ModuleItemMap {
                     | ModuleDefId::MacroId(_)
                     | ModuleDefId::StaticId(_) => return None,
                 };
-                Some(ResolveValueResult::Partial(ty, idx, def.import))
+                Some((ResolveValueResult::Partial(ty, unresolved_idx, def.import), prefix_info))
             }
         }
     }
@@ -958,7 +987,7 @@ impl ModuleItemMap {
         db: &dyn DefDatabase,
         path: &ModPath,
     ) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>)> {
-        let (module_def, idx) =
+        let (module_def, idx, _) =
             self.def_map.resolve_path_locally(db, self.module_id, path, BuiltinShadowMode::Other);
         let (res, import) = to_type_ns(module_def)?;
         Some((res, idx, import))
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 12df3cf2188..c9c793d54f2 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs
@@ -19,7 +19,7 @@ use crate::{
     db::ExpandDatabase,
     mod_path::ModPath,
     span_map::SpanMapRef,
-    tt::{self, token_to_literal, Subtree},
+    tt::{self, token_to_literal, TopSubtree},
     InFile,
 };
 
@@ -107,8 +107,8 @@ impl RawAttrs {
                     .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.id.cfg_attr_index().unwrap_or(0) as u32)
+                                << AttrId::AST_INDEX_BITS);
                         it
                     }))
                     .collect::<Vec<_>>();
@@ -122,7 +122,7 @@ impl RawAttrs {
     pub fn filter(self, db: &dyn ExpandDatabase, krate: CrateId) -> RawAttrs {
         let has_cfg_attrs = self
             .iter()
-            .any(|attr| attr.path.as_ident().map_or(false, |name| *name == sym::cfg_attr.clone()));
+            .any(|attr| attr.path.as_ident().is_some_and(|name| *name == sym::cfg_attr.clone()));
         if !has_cfg_attrs {
             return self;
         }
@@ -132,7 +132,7 @@ impl RawAttrs {
             self.iter()
                 .flat_map(|attr| -> SmallVec<[_; 1]> {
                     let is_cfg_attr =
-                        attr.path.as_ident().map_or(false, |name| *name == sym::cfg_attr.clone());
+                        attr.path.as_ident().is_some_and(|name| *name == sym::cfg_attr.clone());
                     if !is_cfg_attr {
                         return smallvec![attr.clone()];
                     }
@@ -152,7 +152,7 @@ impl RawAttrs {
                     );
 
                     let cfg_options = &crate_graph[krate].cfg_options;
-                    let cfg = Subtree { delimiter: subtree.delimiter, token_trees: Box::from(cfg) };
+                    let cfg = TopSubtree::from_token_trees(subtree.top_subtree().delimiter, cfg);
                     let cfg = CfgExpr::parse(&cfg);
                     if cfg_options.check(&cfg) == Some(false) {
                         smallvec![]
@@ -202,7 +202,7 @@ impl AttrId {
     }
 
     pub fn with_cfg_attr(self, idx: usize) -> AttrId {
-        AttrId { id: self.id | (idx as u32) << Self::AST_INDEX_BITS | Self::CFG_ATTR_SET_BITS }
+        AttrId { id: self.id | ((idx as u32) << Self::AST_INDEX_BITS) | Self::CFG_ATTR_SET_BITS }
     }
 }
 
@@ -219,7 +219,7 @@ pub enum AttrInput {
     /// `#[attr = "string"]`
     Literal(tt::Literal),
     /// `#[attr(subtree)]`
-    TokenTree(Box<tt::Subtree>),
+    TokenTree(tt::TopSubtree),
 }
 
 impl fmt::Display for AttrInput {
@@ -254,46 +254,59 @@ impl Attr {
                 span,
                 DocCommentDesugarMode::ProcMacro,
             );
-            Some(Box::new(AttrInput::TokenTree(Box::new(tree))))
+            Some(Box::new(AttrInput::TokenTree(tree)))
         } else {
             None
         };
         Some(Attr { id, path, input, ctxt: span.ctx })
     }
 
-    fn from_tt(db: &dyn ExpandDatabase, mut tt: &[tt::TokenTree], id: AttrId) -> Option<Attr> {
-        if matches!(tt,
+    fn from_tt(
+        db: &dyn ExpandDatabase,
+        mut tt: tt::TokenTreesView<'_>,
+        id: AttrId,
+    ) -> Option<Attr> {
+        if matches!(tt.flat_tokens(),
             [tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { sym, .. })), ..]
             if *sym == sym::unsafe_
         ) {
-            match tt.get(1) {
-                Some(tt::TokenTree::Subtree(subtree)) => tt = &subtree.token_trees,
+            match tt.iter().nth(1) {
+                Some(tt::TtElement::Subtree(_, iter)) => tt = iter.remaining(),
                 _ => return None,
             }
         }
-        let first = &tt.first()?;
+        let first = tt.flat_tokens().first()?;
         let ctxt = first.first_span().ctx;
-        let path_end = tt
-            .iter()
-            .position(|tt| {
-                !matches!(
+        let (path, input) = {
+            let mut iter = tt.iter();
+            let start = iter.savepoint();
+            let mut input = tt::TokenTreesView::new(&[]);
+            let mut path = iter.from_savepoint(start);
+            let mut path_split_savepoint = iter.savepoint();
+            while let Some(tt) = iter.next() {
+                path = iter.from_savepoint(start);
+                if !matches!(
                     tt,
-                    tt::TokenTree::Leaf(
+                    tt::TtElement::Leaf(
                         tt::Leaf::Punct(tt::Punct { char: ':' | '$', .. }) | tt::Leaf::Ident(_),
                     )
-                )
-            })
-            .unwrap_or(tt.len());
+                ) {
+                    input = path_split_savepoint.remaining();
+                    break;
+                }
+                path_split_savepoint = iter.savepoint();
+            }
+            (path, input)
+        };
 
-        let (path, input) = tt.split_at(path_end);
         let path = Interned::new(ModPath::from_tt(db, path)?);
 
-        let input = match input.first() {
-            Some(tt::TokenTree::Subtree(tree)) => {
-                Some(Box::new(AttrInput::TokenTree(Box::new(tree.clone()))))
+        let input = match (input.flat_tokens().first(), input.try_into_subtree()) {
+            (_, Some(tree)) => {
+                Some(Box::new(AttrInput::TokenTree(tt::TopSubtree::from_subtree(tree))))
             }
-            Some(tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: '=', .. }))) => {
-                let input = match input.get(1) {
+            (Some(tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: '=', .. }))), _) => {
+                let input = match input.flat_tokens().get(1) {
                     Some(tt::TokenTree::Leaf(tt::Leaf::Literal(lit))) => {
                         Some(Box::new(AttrInput::Literal(lit.clone())))
                     }
@@ -352,7 +365,7 @@ impl Attr {
     /// #[path(ident)]
     pub fn single_ident_value(&self) -> Option<&tt::Ident> {
         match self.input.as_deref()? {
-            AttrInput::TokenTree(tt) => match &*tt.token_trees {
+            AttrInput::TokenTree(tt) => match tt.token_trees().flat_tokens() {
                 [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] => Some(ident),
                 _ => None,
             },
@@ -361,7 +374,7 @@ impl Attr {
     }
 
     /// #[path TokenTree]
-    pub fn token_tree_value(&self) -> Option<&Subtree> {
+    pub fn token_tree_value(&self) -> Option<&TopSubtree> {
         match self.input.as_deref()? {
             AttrInput::TokenTree(tt) => Some(tt),
             _ => None,
@@ -375,14 +388,14 @@ impl Attr {
     ) -> Option<impl Iterator<Item = (ModPath, Span)> + 'a> {
         let args = self.token_tree_value()?;
 
-        if args.delimiter.kind != DelimiterKind::Parenthesis {
+        if args.top_subtree().delimiter.kind != DelimiterKind::Parenthesis {
             return None;
         }
         let paths = args
-            .token_trees
-            .split(|tt| matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(Punct { char: ',', .. }))))
+            .token_trees()
+            .split(|tt| matches!(tt, tt::TtElement::Leaf(tt::Leaf::Punct(Punct { char: ',', .. }))))
             .filter_map(move |tts| {
-                let span = tts.first()?.first_span();
+                let span = tts.flat_tokens().first()?.first_span();
                 Some((ModPath::from_tt(db, tts)?, span))
             });
 
@@ -467,11 +480,11 @@ fn inner_attributes(
 // Input subtree is: `(cfg, $(attr),+)`
 // Split it up into a `cfg` subtree and the `attr` subtrees.
 fn parse_cfg_attr_input(
-    subtree: &Subtree,
-) -> Option<(&[tt::TokenTree], impl Iterator<Item = &[tt::TokenTree]>)> {
+    subtree: &TopSubtree,
+) -> Option<(tt::TokenTreesView<'_>, impl Iterator<Item = tt::TokenTreesView<'_>>)> {
     let mut parts = subtree
-        .token_trees
-        .split(|tt| matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(Punct { char: ',', .. }))));
+        .token_trees()
+        .split(|tt| matches!(tt, tt::TtElement::Leaf(tt::Leaf::Punct(Punct { char: ',', .. }))));
     let cfg = parts.next()?;
     Some((cfg, parts.filter(|it| !it.is_empty())))
 }
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/attr_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/attr_macro.rs
index 74effd2fb16..f250620e775 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/attr_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/attr_macro.rs
@@ -14,7 +14,7 @@ macro_rules! register_builtin {
         }
 
         impl BuiltinAttrExpander {
-            pub fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::Subtree, Span) -> ExpandResult<tt::Subtree>  {
+            pub fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::TopSubtree, Span) -> ExpandResult<tt::TopSubtree>  {
                 match *self {
                     $( BuiltinAttrExpander::$variant => $expand, )*
                 }
@@ -36,9 +36,9 @@ impl BuiltinAttrExpander {
         &self,
         db: &dyn ExpandDatabase,
         id: MacroCallId,
-        tt: &tt::Subtree,
+        tt: &tt::TopSubtree,
         span: Span,
-    ) -> ExpandResult<tt::Subtree> {
+    ) -> ExpandResult<tt::TopSubtree> {
         self.expander()(db, id, tt, span)
     }
 
@@ -75,18 +75,18 @@ pub fn find_builtin_attr(ident: &name::Name) -> Option<BuiltinAttrExpander> {
 fn dummy_attr_expand(
     _db: &dyn ExpandDatabase,
     _id: MacroCallId,
-    tt: &tt::Subtree,
+    tt: &tt::TopSubtree,
     _span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
     ExpandResult::ok(tt.clone())
 }
 
 fn dummy_gate_test_expand(
     _db: &dyn ExpandDatabase,
     _id: MacroCallId,
-    tt: &tt::Subtree,
+    tt: &tt::TopSubtree,
     span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
     let result = quote::quote! { span=>
         #[cfg(test)]
         #tt
@@ -118,47 +118,41 @@ fn dummy_gate_test_expand(
 fn derive_expand(
     db: &dyn ExpandDatabase,
     id: MacroCallId,
-    tt: &tt::Subtree,
+    tt: &tt::TopSubtree,
     span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
     let loc = db.lookup_intern_macro_call(id);
     let derives = match &loc.kind {
         MacroCallKind::Attr { attr_args: Some(attr_args), .. } if loc.def.is_attribute_derive() => {
             attr_args
         }
         _ => {
-            return ExpandResult::ok(tt::Subtree::empty(tt::DelimSpan { open: span, close: span }))
+            return ExpandResult::ok(tt::TopSubtree::empty(tt::DelimSpan {
+                open: span,
+                close: span,
+            }))
         }
     };
     pseudo_derive_attr_expansion(tt, derives, span)
 }
 
 pub fn pseudo_derive_attr_expansion(
-    _: &tt::Subtree,
-    args: &tt::Subtree,
+    _: &tt::TopSubtree,
+    args: &tt::TopSubtree,
     call_site: Span,
-) -> ExpandResult<tt::Subtree> {
-    let mk_leaf = |char| {
-        tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct {
-            char,
-            spacing: tt::Spacing::Alone,
-            span: call_site,
-        }))
-    };
+) -> ExpandResult<tt::TopSubtree> {
+    let mk_leaf =
+        |char| tt::Leaf::Punct(tt::Punct { char, spacing: tt::Spacing::Alone, span: call_site });
 
-    let mut token_trees = Vec::new();
-    for tt in args
-        .token_trees
-        .split(|tt| matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: ',', .. }))))
-    {
-        token_trees.push(mk_leaf('#'));
-        token_trees.push(mk_leaf('!'));
-        token_trees.push(mk_leaf('['));
-        token_trees.extend(tt.iter().cloned());
-        token_trees.push(mk_leaf(']'));
+    let mut token_trees = tt::TopSubtreeBuilder::new(args.top_subtree().delimiter);
+    let iter = args.token_trees().split(|tt| {
+        matches!(tt, tt::TtElement::Leaf(tt::Leaf::Punct(tt::Punct { char: ',', .. })))
+    });
+    for tts in iter {
+        token_trees.extend([mk_leaf('#'), mk_leaf('!')]);
+        token_trees.open(tt::DelimiterKind::Bracket, call_site);
+        token_trees.extend_with_tt(tts);
+        token_trees.close(call_site);
     }
-    ExpandResult::ok(tt::Subtree {
-        delimiter: args.delimiter,
-        token_trees: token_trees.into_boxed_slice(),
-    })
+    ExpandResult::ok(token_trees.build())
 }
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs
index 7d3e8deaf08..4510a593af4 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/derive_macro.rs
@@ -1,9 +1,10 @@
 //! Builtin derives.
 
 use intern::sym;
-use itertools::izip;
+use itertools::{izip, Itertools};
+use parser::SyntaxKind;
 use rustc_hash::FxHashSet;
-use span::{MacroCallId, Span};
+use span::{MacroCallId, Span, SyntaxContextId};
 use stdx::never;
 use syntax_bridge::DocCommentDesugarMode;
 use tracing::debug;
@@ -16,8 +17,12 @@ use crate::{
     span_map::ExpansionSpanMap,
     tt, ExpandError, ExpandResult,
 };
-use syntax::ast::{
-    self, AstNode, FieldList, HasAttrs, HasGenericParams, HasModuleItem, HasName, HasTypeBounds,
+use syntax::{
+    ast::{
+        self, edit_in_place::GenericParamsOwnerEdit, make, AstNode, FieldList, HasAttrs,
+        HasGenericArgs, HasGenericParams, HasModuleItem, HasName, HasTypeBounds,
+    },
+    ted,
 };
 
 macro_rules! register_builtin {
@@ -28,7 +33,7 @@ macro_rules! register_builtin {
         }
 
         impl BuiltinDeriveExpander {
-            pub fn expander(&self) -> fn(Span, &tt::Subtree) -> ExpandResult<tt::Subtree>  {
+            pub fn expander(&self) -> fn(Span, &tt::TopSubtree) -> ExpandResult<tt::TopSubtree>  {
                 match *self {
                     $( BuiltinDeriveExpander::$trait => $expand, )*
                 }
@@ -50,9 +55,9 @@ impl BuiltinDeriveExpander {
         &self,
         db: &dyn ExpandDatabase,
         id: MacroCallId,
-        tt: &tt::Subtree,
+        tt: &tt::TopSubtree,
         span: Span,
-    ) -> ExpandResult<tt::Subtree> {
+    ) -> ExpandResult<tt::TopSubtree> {
         let span = span_with_def_site_ctxt(db, span, id);
         self.expander()(span, tt)
     }
@@ -67,13 +72,15 @@ register_builtin! {
     Ord => ord_expand,
     PartialOrd => partial_ord_expand,
     Eq => eq_expand,
-    PartialEq => partial_eq_expand
+    PartialEq => partial_eq_expand,
+    CoercePointee => coerce_pointee_expand
 }
 
 pub fn find_builtin_derive(ident: &name::Name) -> Option<BuiltinDeriveExpander> {
     BuiltinDeriveExpander::find_by_name(ident)
 }
 
+#[derive(Clone)]
 enum VariantShape {
     Struct(Vec<tt::Ident>),
     Tuple(usize),
@@ -85,7 +92,7 @@ fn tuple_field_iterator(span: Span, n: usize) -> impl Iterator<Item = tt::Ident>
 }
 
 impl VariantShape {
-    fn as_pattern(&self, path: tt::Subtree, span: Span) -> tt::Subtree {
+    fn as_pattern(&self, path: tt::TopSubtree, span: Span) -> tt::TopSubtree {
         self.as_pattern_map(path, span, |it| quote!(span => #it))
     }
 
@@ -99,10 +106,10 @@ impl VariantShape {
 
     fn as_pattern_map(
         &self,
-        path: tt::Subtree,
+        path: tt::TopSubtree,
         span: Span,
-        field_map: impl Fn(&tt::Ident) -> tt::Subtree,
-    ) -> tt::Subtree {
+        field_map: impl Fn(&tt::Ident) -> tt::TopSubtree,
+    ) -> tt::TopSubtree {
         match self {
             VariantShape::Struct(fields) => {
                 let fields = fields.iter().map(|it| {
@@ -147,6 +154,7 @@ impl VariantShape {
     }
 }
 
+#[derive(Clone)]
 enum AdtShape {
     Struct(VariantShape),
     Enum { variants: Vec<(tt::Ident, VariantShape)>, default_variant: Option<usize> },
@@ -154,7 +162,7 @@ enum AdtShape {
 }
 
 impl AdtShape {
-    fn as_pattern(&self, span: Span, name: &tt::Ident) -> Vec<tt::Subtree> {
+    fn as_pattern(&self, span: Span, name: &tt::Ident) -> Vec<tt::TopSubtree> {
         self.as_pattern_map(name, |it| quote!(span =>#it), span)
     }
 
@@ -176,9 +184,9 @@ impl AdtShape {
     fn as_pattern_map(
         &self,
         name: &tt::Ident,
-        field_map: impl Fn(&tt::Ident) -> tt::Subtree,
+        field_map: impl Fn(&tt::Ident) -> tt::TopSubtree,
         span: Span,
-    ) -> Vec<tt::Subtree> {
+    ) -> Vec<tt::TopSubtree> {
         match self {
             AdtShape::Struct(s) => {
                 vec![s.as_pattern_map(quote! {span => #name }, span, field_map)]
@@ -197,30 +205,38 @@ impl AdtShape {
     }
 }
 
+#[derive(Clone)]
 struct BasicAdtInfo {
     name: tt::Ident,
     shape: AdtShape,
     /// first field is the name, and
     /// second field is `Some(ty)` if it's a const param of type `ty`, `None` if it's a type param.
     /// third fields is where bounds, if any
-    param_types: Vec<(tt::Subtree, Option<tt::Subtree>, Option<tt::Subtree>)>,
-    where_clause: Vec<tt::Subtree>,
-    associated_types: Vec<tt::Subtree>,
+    param_types: Vec<AdtParam>,
+    where_clause: Vec<tt::TopSubtree>,
+    associated_types: Vec<tt::TopSubtree>,
 }
 
-fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result<BasicAdtInfo, ExpandError> {
-    let (parsed, tm) = &syntax_bridge::token_tree_to_syntax_node(
-        tt,
-        syntax_bridge::TopEntryPoint::MacroItems,
-        parser::Edition::CURRENT_FIXME,
-    );
-    let macro_items = ast::MacroItems::cast(parsed.syntax_node())
-        .ok_or_else(|| ExpandError::other(call_site, "invalid item definition"))?;
-    let item =
-        macro_items.items().next().ok_or_else(|| ExpandError::other(call_site, "no item found"))?;
-    let adt = &ast::Adt::cast(item.syntax().clone())
-        .ok_or_else(|| ExpandError::other(call_site, "expected struct, enum or union"))?;
-    let (name, generic_param_list, where_clause, shape) = match adt {
+#[derive(Clone)]
+struct AdtParam {
+    name: tt::TopSubtree,
+    /// `None` if this is a type parameter.
+    const_ty: Option<tt::TopSubtree>,
+    bounds: Option<tt::TopSubtree>,
+}
+
+// FIXME: This whole thing needs a refactor. Each derive requires its special values, and the result is a mess.
+fn parse_adt(tt: &tt::TopSubtree, call_site: Span) -> Result<BasicAdtInfo, ExpandError> {
+    let (adt, tm) = to_adt_syntax(tt, call_site)?;
+    parse_adt_from_syntax(&adt, &tm, call_site)
+}
+
+fn parse_adt_from_syntax(
+    adt: &ast::Adt,
+    tm: &span::SpanMap<SyntaxContextId>,
+    call_site: Span,
+) -> Result<BasicAdtInfo, ExpandError> {
+    let (name, generic_param_list, where_clause, shape) = match &adt {
         ast::Adt::Struct(it) => (
             it.name(),
             it.generic_param_list(),
@@ -276,7 +292,7 @@ fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result<BasicAdtInfo, ExpandEr
                         )
                     }
                     None => {
-                        tt::Subtree::empty(::tt::DelimSpan { open: call_site, close: call_site })
+                        tt::TopSubtree::empty(::tt::DelimSpan { open: call_site, close: call_site })
                     }
                 }
             };
@@ -291,7 +307,7 @@ fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result<BasicAdtInfo, ExpandEr
                 }),
                 ast::TypeOrConstParam::Const(_) => None,
             };
-            let ty = if let ast::TypeOrConstParam::Const(param) = param {
+            let const_ty = if let ast::TypeOrConstParam::Const(param) = param {
                 let ty = param
                     .ty()
                     .map(|ty| {
@@ -303,13 +319,13 @@ fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result<BasicAdtInfo, ExpandEr
                         )
                     })
                     .unwrap_or_else(|| {
-                        tt::Subtree::empty(::tt::DelimSpan { open: call_site, close: call_site })
+                        tt::TopSubtree::empty(::tt::DelimSpan { open: call_site, close: call_site })
                     });
                 Some(ty)
             } else {
                 None
             };
-            (name, ty, bounds)
+            AdtParam { name, const_ty, bounds }
         })
         .collect();
 
@@ -365,6 +381,24 @@ fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result<BasicAdtInfo, ExpandEr
     Ok(BasicAdtInfo { name: name_token, shape, param_types, where_clause, associated_types })
 }
 
+fn to_adt_syntax(
+    tt: &tt::TopSubtree,
+    call_site: Span,
+) -> Result<(ast::Adt, span::SpanMap<SyntaxContextId>), ExpandError> {
+    let (parsed, tm) = syntax_bridge::token_tree_to_syntax_node(
+        tt,
+        syntax_bridge::TopEntryPoint::MacroItems,
+        parser::Edition::CURRENT_FIXME,
+    );
+    let macro_items = ast::MacroItems::cast(parsed.syntax_node())
+        .ok_or_else(|| ExpandError::other(call_site, "invalid item definition"))?;
+    let item =
+        macro_items.items().next().ok_or_else(|| ExpandError::other(call_site, "no item found"))?;
+    let adt = ast::Adt::cast(item.syntax().clone())
+        .ok_or_else(|| ExpandError::other(call_site, "expected struct, enum or union"))?;
+    Ok((adt, tm))
+}
+
 fn name_to_token(
     call_site: Span,
     token_map: &ExpansionSpanMap,
@@ -413,59 +447,85 @@ fn name_to_token(
 /// therefore does not get bound by the derived trait.
 fn expand_simple_derive(
     invoc_span: Span,
-    tt: &tt::Subtree,
-    trait_path: tt::Subtree,
-    make_trait_body: impl FnOnce(&BasicAdtInfo) -> tt::Subtree,
-) -> ExpandResult<tt::Subtree> {
+    tt: &tt::TopSubtree,
+    trait_path: tt::TopSubtree,
+    make_trait_body: impl FnOnce(&BasicAdtInfo) -> tt::TopSubtree,
+) -> ExpandResult<tt::TopSubtree> {
     let info = match parse_adt(tt, invoc_span) {
         Ok(info) => info,
         Err(e) => {
             return ExpandResult::new(
-                tt::Subtree::empty(tt::DelimSpan { open: invoc_span, close: invoc_span }),
+                tt::TopSubtree::empty(tt::DelimSpan { open: invoc_span, close: invoc_span }),
                 e,
             )
         }
     };
+    ExpandResult::ok(expand_simple_derive_with_parsed(
+        invoc_span,
+        info,
+        trait_path,
+        make_trait_body,
+        true,
+        tt::TopSubtree::empty(tt::DelimSpan::from_single(invoc_span)),
+    ))
+}
+
+fn expand_simple_derive_with_parsed(
+    invoc_span: Span,
+    info: BasicAdtInfo,
+    trait_path: tt::TopSubtree,
+    make_trait_body: impl FnOnce(&BasicAdtInfo) -> tt::TopSubtree,
+    constrain_to_trait: bool,
+    extra_impl_params: tt::TopSubtree,
+) -> tt::TopSubtree {
     let trait_body = make_trait_body(&info);
     let mut where_block: Vec<_> =
         info.where_clause.into_iter().map(|w| quote! {invoc_span => #w , }).collect();
     let (params, args): (Vec<_>, Vec<_>) = info
         .param_types
         .into_iter()
-        .map(|(ident, param_ty, bound)| {
-            let ident_ = ident.clone();
-            if let Some(b) = bound {
-                let ident = ident.clone();
-                where_block.push(quote! {invoc_span => #ident : #b , });
-            }
-            if let Some(ty) = param_ty {
-                (quote! {invoc_span => const #ident : #ty , }, quote! {invoc_span => #ident_ , })
+        .map(|param| {
+            let ident = param.name;
+            if let Some(b) = param.bounds {
+                let ident2 = ident.clone();
+                where_block.push(quote! {invoc_span => #ident2 : #b , });
+            }
+            if let Some(ty) = param.const_ty {
+                let ident2 = ident.clone();
+                (quote! {invoc_span => const #ident : #ty , }, quote! {invoc_span => #ident2 , })
             } else {
                 let bound = trait_path.clone();
-                (quote! {invoc_span => #ident : #bound , }, quote! {invoc_span => #ident_ , })
+                let ident2 = ident.clone();
+                let param = if constrain_to_trait {
+                    quote! {invoc_span => #ident : #bound , }
+                } else {
+                    quote! {invoc_span => #ident , }
+                };
+                (param, quote! {invoc_span => #ident2 , })
             }
         })
         .unzip();
 
-    where_block.extend(info.associated_types.iter().map(|it| {
-        let it = it.clone();
-        let bound = trait_path.clone();
-        quote! {invoc_span => #it : #bound , }
-    }));
+    if constrain_to_trait {
+        where_block.extend(info.associated_types.iter().map(|it| {
+            let it = it.clone();
+            let bound = trait_path.clone();
+            quote! {invoc_span => #it : #bound , }
+        }));
+    }
 
     let name = info.name;
-    let expanded = quote! {invoc_span =>
-        impl < ##params > #trait_path for #name < ##args > where ##where_block { #trait_body }
-    };
-    ExpandResult::ok(expanded)
+    quote! {invoc_span =>
+        impl < ##params #extra_impl_params > #trait_path for #name < ##args > where ##where_block { #trait_body }
+    }
 }
 
-fn copy_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
+fn copy_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> {
     let krate = dollar_crate(span);
     expand_simple_derive(span, tt, quote! {span => #krate::marker::Copy }, |_| quote! {span =>})
 }
 
-fn clone_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
+fn clone_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> {
     let krate = dollar_crate(span);
     expand_simple_derive(span, tt, quote! {span => #krate::clone::Clone }, |adt| {
         if matches!(adt.shape, AdtShape::Union) {
@@ -505,18 +565,18 @@ fn clone_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
 }
 
 /// This function exists since `quote! {span => => }` doesn't work.
-fn fat_arrow(span: Span) -> tt::Subtree {
+fn fat_arrow(span: Span) -> tt::TopSubtree {
     let eq = tt::Punct { char: '=', spacing: ::tt::Spacing::Joint, span };
     quote! {span => #eq> }
 }
 
 /// This function exists since `quote! {span => && }` doesn't work.
-fn and_and(span: Span) -> tt::Subtree {
+fn and_and(span: Span) -> tt::TopSubtree {
     let and = tt::Punct { char: '&', spacing: ::tt::Spacing::Joint, span };
     quote! {span => #and& }
 }
 
-fn default_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
+fn default_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> {
     let krate = &dollar_crate(span);
     expand_simple_derive(span, tt, quote! {span => #krate::default::Default }, |adt| {
         let body = match &adt.shape {
@@ -555,7 +615,7 @@ fn default_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
     })
 }
 
-fn debug_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
+fn debug_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> {
     let krate = &dollar_crate(span);
     expand_simple_derive(span, tt, quote! {span => #krate::fmt::Debug }, |adt| {
         let for_variant = |name: String, v: &VariantShape| match v {
@@ -627,7 +687,7 @@ fn debug_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
     })
 }
 
-fn hash_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
+fn hash_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> {
     let krate = &dollar_crate(span);
     expand_simple_derive(span, tt, quote! {span => #krate::hash::Hash }, |adt| {
         if matches!(adt.shape, AdtShape::Union) {
@@ -674,12 +734,12 @@ fn hash_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
     })
 }
 
-fn eq_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
+fn eq_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> {
     let krate = dollar_crate(span);
     expand_simple_derive(span, tt, quote! {span => #krate::cmp::Eq }, |_| quote! {span =>})
 }
 
-fn partial_eq_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
+fn partial_eq_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> {
     let krate = dollar_crate(span);
     expand_simple_derive(span, tt, quote! {span => #krate::cmp::PartialEq }, |adt| {
         if matches!(adt.shape, AdtShape::Union) {
@@ -731,7 +791,7 @@ fn self_and_other_patterns(
     adt: &BasicAdtInfo,
     name: &tt::Ident,
     span: Span,
-) -> (Vec<tt::Subtree>, Vec<tt::Subtree>) {
+) -> (Vec<tt::TopSubtree>, Vec<tt::TopSubtree>) {
     let self_patterns = adt.shape.as_pattern_map(
         name,
         |it| {
@@ -751,16 +811,16 @@ fn self_and_other_patterns(
     (self_patterns, other_patterns)
 }
 
-fn ord_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
+fn ord_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> {
     let krate = &dollar_crate(span);
     expand_simple_derive(span, tt, quote! {span => #krate::cmp::Ord }, |adt| {
         fn compare(
             krate: &tt::Ident,
-            left: tt::Subtree,
-            right: tt::Subtree,
-            rest: tt::Subtree,
+            left: tt::TopSubtree,
+            right: tt::TopSubtree,
+            rest: tt::TopSubtree,
             span: Span,
-        ) -> tt::Subtree {
+        ) -> tt::TopSubtree {
             let fat_arrow1 = fat_arrow(span);
             let fat_arrow2 = fat_arrow(span);
             quote! {span =>
@@ -809,16 +869,16 @@ fn ord_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
     })
 }
 
-fn partial_ord_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
+fn partial_ord_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> {
     let krate = &dollar_crate(span);
     expand_simple_derive(span, tt, quote! {span => #krate::cmp::PartialOrd }, |adt| {
         fn compare(
             krate: &tt::Ident,
-            left: tt::Subtree,
-            right: tt::Subtree,
-            rest: tt::Subtree,
+            left: tt::TopSubtree,
+            right: tt::TopSubtree,
+            rest: tt::TopSubtree,
             span: Span,
-        ) -> tt::Subtree {
+        ) -> tt::TopSubtree {
             let fat_arrow1 = fat_arrow(span);
             let fat_arrow2 = fat_arrow(span);
             quote! {span =>
@@ -871,3 +931,493 @@ fn partial_ord_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree>
         }
     })
 }
+
+fn coerce_pointee_expand(span: Span, tt: &tt::TopSubtree) -> ExpandResult<tt::TopSubtree> {
+    let (adt, _span_map) = match to_adt_syntax(tt, span) {
+        Ok(it) => it,
+        Err(err) => {
+            return ExpandResult::new(tt::TopSubtree::empty(tt::DelimSpan::from_single(span)), err);
+        }
+    };
+    let adt = adt.clone_for_update();
+    let ast::Adt::Struct(strukt) = &adt else {
+        return ExpandResult::new(
+            tt::TopSubtree::empty(tt::DelimSpan::from_single(span)),
+            ExpandError::other(span, "`CoercePointee` can only be derived on `struct`s"),
+        );
+    };
+    let has_at_least_one_field = strukt
+        .field_list()
+        .map(|it| match it {
+            ast::FieldList::RecordFieldList(it) => it.fields().next().is_some(),
+            ast::FieldList::TupleFieldList(it) => it.fields().next().is_some(),
+        })
+        .unwrap_or(false);
+    if !has_at_least_one_field {
+        return ExpandResult::new(
+            tt::TopSubtree::empty(tt::DelimSpan::from_single(span)),
+            ExpandError::other(
+                span,
+                "`CoercePointee` can only be derived on `struct`s with at least one field",
+            ),
+        );
+    }
+    let is_repr_transparent = strukt.attrs().any(|attr| {
+        attr.as_simple_call().is_some_and(|(name, tt)| {
+            name == "repr"
+                && tt.syntax().children_with_tokens().any(|it| {
+                    it.into_token().is_some_and(|it| {
+                        it.kind() == SyntaxKind::IDENT && it.text() == "transparent"
+                    })
+                })
+        })
+    });
+    if !is_repr_transparent {
+        return ExpandResult::new(
+            tt::TopSubtree::empty(tt::DelimSpan::from_single(span)),
+            ExpandError::other(
+                span,
+                "`CoercePointee` can only be derived on `struct`s with `#[repr(transparent)]`",
+            ),
+        );
+    }
+    let type_params = strukt
+        .generic_param_list()
+        .into_iter()
+        .flat_map(|generics| {
+            generics.generic_params().filter_map(|param| match param {
+                ast::GenericParam::TypeParam(param) => Some(param),
+                _ => None,
+            })
+        })
+        .collect_vec();
+    if type_params.is_empty() {
+        return ExpandResult::new(
+            tt::TopSubtree::empty(tt::DelimSpan::from_single(span)),
+            ExpandError::other(
+                span,
+                "`CoercePointee` can only be derived on `struct`s that are generic over at least one type",
+            ),
+        );
+    }
+    let (pointee_param, pointee_param_idx) = if type_params.len() == 1 {
+        // Regardless of the only type param being designed as `#[pointee]` or not, we can just use it as such.
+        (type_params[0].clone(), 0)
+    } else {
+        let mut pointees = type_params.iter().cloned().enumerate().filter(|(_, param)| {
+            param.attrs().any(|attr| {
+                let is_pointee = attr.as_simple_atom().is_some_and(|name| name == "pointee");
+                if is_pointee {
+                    // Remove the `#[pointee]` attribute so it won't be present in the generated
+                    // impls (where we cannot resolve it).
+                    ted::remove(attr.syntax());
+                }
+                is_pointee
+            })
+        });
+        match (pointees.next(), pointees.next()) {
+            (Some((pointee_idx, pointee)), None) => (pointee, pointee_idx),
+            (None, _) => {
+                return ExpandResult::new(
+                    tt::TopSubtree::empty(tt::DelimSpan::from_single(span)),
+                    ExpandError::other(
+                        span,
+                        "exactly one generic type parameter must be marked \
+                                as `#[pointee]` to derive `CoercePointee` traits",
+                    ),
+                )
+            }
+            (Some(_), Some(_)) => {
+                return ExpandResult::new(
+                    tt::TopSubtree::empty(tt::DelimSpan::from_single(span)),
+                    ExpandError::other(
+                        span,
+                        "only one type parameter can be marked as `#[pointee]` \
+                                when deriving `CoercePointee` traits",
+                    ),
+                )
+            }
+        }
+    };
+    let (Some(struct_name), Some(pointee_param_name)) = (strukt.name(), pointee_param.name())
+    else {
+        return ExpandResult::new(
+            tt::TopSubtree::empty(tt::DelimSpan::from_single(span)),
+            ExpandError::other(span, "invalid item"),
+        );
+    };
+
+    {
+        let mut pointee_has_maybe_sized_bound = false;
+        if let Some(bounds) = pointee_param.type_bound_list() {
+            pointee_has_maybe_sized_bound |= bounds.bounds().any(is_maybe_sized_bound);
+        }
+        if let Some(where_clause) = strukt.where_clause() {
+            pointee_has_maybe_sized_bound |= where_clause.predicates().any(|pred| {
+                let Some(ast::Type::PathType(ty)) = pred.ty() else { return false };
+                let is_not_pointee = ty.path().is_none_or(|path| {
+                    let is_pointee = path
+                        .as_single_name_ref()
+                        .is_some_and(|name| name.text() == pointee_param_name.text());
+                    !is_pointee
+                });
+                if is_not_pointee {
+                    return false;
+                }
+                pred.type_bound_list()
+                    .is_some_and(|bounds| bounds.bounds().any(is_maybe_sized_bound))
+            })
+        }
+        if !pointee_has_maybe_sized_bound {
+            return ExpandResult::new(
+                tt::TopSubtree::empty(tt::DelimSpan::from_single(span)),
+                ExpandError::other(
+                    span,
+                    format!("`derive(CoercePointee)` requires `{pointee_param_name}` to be marked `?Sized`"),
+                ),
+            );
+        }
+    }
+
+    const ADDED_PARAM: &str = "__S";
+
+    let where_clause = strukt.get_or_create_where_clause();
+
+    {
+        let mut new_predicates = Vec::new();
+
+        // # Rewrite generic parameter bounds
+        // For each bound `U: ..` in `struct<U: ..>`, make a new bound with `__S` in place of `#[pointee]`
+        // Example:
+        // ```
+        // struct<
+        //     U: Trait<T>,
+        //     #[pointee] T: Trait<T> + ?Sized,
+        //     V: Trait<T>> ...
+        // ```
+        // ... generates this `impl` generic parameters
+        // ```
+        // impl<
+        //     U: Trait<T>,
+        //     T: Trait<T> + ?Sized,
+        //     V: Trait<T>
+        // >
+        // where
+        //     U: Trait<__S>,
+        //     __S: Trait<__S> + ?Sized,
+        //     V: Trait<__S> ...
+        // ```
+        for param in &type_params {
+            let Some(param_name) = param.name() else { continue };
+            if let Some(bounds) = param.type_bound_list() {
+                // If the target type is the pointee, duplicate the bound as whole.
+                // Otherwise, duplicate only bounds that mention the pointee.
+                let is_pointee = param_name.text() == pointee_param_name.text();
+                let new_bounds = bounds
+                    .bounds()
+                    .map(|bound| bound.clone_subtree().clone_for_update())
+                    .filter(|bound| {
+                        bound.ty().is_some_and(|ty| {
+                            substitute_type_in_bound(ty, &pointee_param_name.text(), ADDED_PARAM)
+                                || is_pointee
+                        })
+                    });
+                let new_bounds_target = if is_pointee {
+                    make::name_ref(ADDED_PARAM)
+                } else {
+                    make::name_ref(&param_name.text())
+                };
+                new_predicates.push(
+                    make::where_pred(
+                        make::ty_path(make::path_from_segments(
+                            [make::path_segment(new_bounds_target)],
+                            false,
+                        )),
+                        new_bounds,
+                    )
+                    .clone_for_update(),
+                );
+            }
+        }
+
+        // # Rewrite `where` clauses
+        //
+        // Move on to `where` clauses.
+        // Example:
+        // ```
+        // struct MyPointer<#[pointee] T, ..>
+        // where
+        //   U: Trait<V> + Trait<T>,
+        //   Companion<T>: Trait<T>,
+        //   T: Trait<T> + ?Sized,
+        // { .. }
+        // ```
+        // ... will have a impl prelude like so
+        // ```
+        // impl<..> ..
+        // where
+        //   U: Trait<V> + Trait<T>,
+        //   U: Trait<__S>,
+        //   Companion<T>: Trait<T>,
+        //   Companion<__S>: Trait<__S>,
+        //   T: Trait<T> + ?Sized,
+        //   __S: Trait<__S> + ?Sized,
+        // ```
+        //
+        // We should also write a few new `where` bounds from `#[pointee] T` to `__S`
+        // as well as any bound that indirectly involves the `#[pointee] T` type.
+        for predicate in where_clause.predicates() {
+            let predicate = predicate.clone_subtree().clone_for_update();
+            let Some(pred_target) = predicate.ty() else { continue };
+
+            // If the target type references the pointee, duplicate the bound as whole.
+            // Otherwise, duplicate only bounds that mention the pointee.
+            if substitute_type_in_bound(
+                pred_target.clone(),
+                &pointee_param_name.text(),
+                ADDED_PARAM,
+            ) {
+                if let Some(bounds) = predicate.type_bound_list() {
+                    for bound in bounds.bounds() {
+                        if let Some(ty) = bound.ty() {
+                            substitute_type_in_bound(ty, &pointee_param_name.text(), ADDED_PARAM);
+                        }
+                    }
+                }
+
+                new_predicates.push(predicate);
+            } else if let Some(bounds) = predicate.type_bound_list() {
+                let new_bounds = bounds
+                    .bounds()
+                    .map(|bound| bound.clone_subtree().clone_for_update())
+                    .filter(|bound| {
+                        bound.ty().is_some_and(|ty| {
+                            substitute_type_in_bound(ty, &pointee_param_name.text(), ADDED_PARAM)
+                        })
+                    });
+                new_predicates.push(make::where_pred(pred_target, new_bounds).clone_for_update());
+            }
+        }
+
+        for new_predicate in new_predicates {
+            where_clause.add_predicate(new_predicate);
+        }
+    }
+
+    {
+        // # Add `Unsize<__S>` bound to `#[pointee]` at the generic parameter location
+        //
+        // Find the `#[pointee]` parameter and add an `Unsize<__S>` bound to it.
+        where_clause.add_predicate(
+            make::where_pred(
+                make::ty_path(make::path_from_segments(
+                    [make::path_segment(make::name_ref(&pointee_param_name.text()))],
+                    false,
+                )),
+                [make::type_bound(make::ty_path(make::path_from_segments(
+                    [
+                        make::path_segment(make::name_ref("core")),
+                        make::path_segment(make::name_ref("marker")),
+                        make::generic_ty_path_segment(
+                            make::name_ref("Unsize"),
+                            [make::type_arg(make::ty_path(make::path_from_segments(
+                                [make::path_segment(make::name_ref(ADDED_PARAM))],
+                                false,
+                            )))
+                            .into()],
+                        ),
+                    ],
+                    true,
+                )))],
+            )
+            .clone_for_update(),
+        );
+    }
+
+    let self_for_traits = {
+        // Replace the `#[pointee]` with `__S`.
+        let mut type_param_idx = 0;
+        let self_params_for_traits = strukt
+            .generic_param_list()
+            .into_iter()
+            .flat_map(|params| params.generic_params())
+            .filter_map(|param| {
+                Some(match param {
+                    ast::GenericParam::ConstParam(param) => {
+                        ast::GenericArg::ConstArg(make::expr_const_value(&param.name()?.text()))
+                    }
+                    ast::GenericParam::LifetimeParam(param) => {
+                        make::lifetime_arg(param.lifetime()?).into()
+                    }
+                    ast::GenericParam::TypeParam(param) => {
+                        let name = if pointee_param_idx == type_param_idx {
+                            make::name_ref(ADDED_PARAM)
+                        } else {
+                            make::name_ref(&param.name()?.text())
+                        };
+                        type_param_idx += 1;
+                        make::type_arg(make::ty_path(make::path_from_segments(
+                            [make::path_segment(name)],
+                            false,
+                        )))
+                        .into()
+                    }
+                })
+            });
+        let self_for_traits = make::path_from_segments(
+            [make::generic_ty_path_segment(
+                make::name_ref(&struct_name.text()),
+                self_params_for_traits,
+            )],
+            false,
+        )
+        .clone_for_update();
+        self_for_traits
+    };
+
+    let mut span_map = span::SpanMap::empty();
+    // One span for them all.
+    span_map.push(adt.syntax().text_range().end(), span);
+
+    let self_for_traits = syntax_bridge::syntax_node_to_token_tree(
+        self_for_traits.syntax(),
+        &span_map,
+        span,
+        DocCommentDesugarMode::ProcMacro,
+    );
+    let info = match parse_adt_from_syntax(&adt, &span_map, span) {
+        Ok(it) => it,
+        Err(err) => {
+            return ExpandResult::new(tt::TopSubtree::empty(tt::DelimSpan::from_single(span)), err)
+        }
+    };
+
+    let self_for_traits2 = self_for_traits.clone();
+    let krate = dollar_crate(span);
+    let krate2 = krate.clone();
+    let dispatch_from_dyn = expand_simple_derive_with_parsed(
+        span,
+        info.clone(),
+        quote! {span => #krate2::ops::DispatchFromDyn<#self_for_traits2> },
+        |_adt| quote! {span => },
+        false,
+        quote! {span => __S },
+    );
+    let coerce_unsized = expand_simple_derive_with_parsed(
+        span,
+        info,
+        quote! {span => #krate::ops::CoerceUnsized<#self_for_traits> },
+        |_adt| quote! {span => },
+        false,
+        quote! {span => __S },
+    );
+    return ExpandResult::ok(quote! {span => #dispatch_from_dyn #coerce_unsized });
+
+    fn is_maybe_sized_bound(bound: ast::TypeBound) -> bool {
+        if bound.question_mark_token().is_none() {
+            return false;
+        }
+        let Some(ast::Type::PathType(ty)) = bound.ty() else {
+            return false;
+        };
+        let Some(path) = ty.path() else {
+            return false;
+        };
+        return segments_eq(&path, &["Sized"])
+            || segments_eq(&path, &["core", "marker", "Sized"])
+            || segments_eq(&path, &["std", "marker", "Sized"]);
+
+        fn segments_eq(path: &ast::Path, expected: &[&str]) -> bool {
+            path.segments().zip_longest(expected.iter().copied()).all(|value| {
+                value.both().is_some_and(|(segment, expected)| {
+                    segment.name_ref().is_some_and(|name| name.text() == expected)
+                })
+            })
+        }
+    }
+
+    /// Returns true if any substitution was performed.
+    fn substitute_type_in_bound(ty: ast::Type, param_name: &str, replacement: &str) -> bool {
+        return match ty {
+            ast::Type::ArrayType(ty) => {
+                ty.ty().is_some_and(|ty| substitute_type_in_bound(ty, param_name, replacement))
+            }
+            ast::Type::DynTraitType(ty) => go_bounds(ty.type_bound_list(), param_name, replacement),
+            ast::Type::FnPtrType(ty) => any_long(
+                ty.param_list()
+                    .into_iter()
+                    .flat_map(|params| params.params().filter_map(|param| param.ty()))
+                    .chain(ty.ret_type().and_then(|it| it.ty())),
+                |ty| substitute_type_in_bound(ty, param_name, replacement),
+            ),
+            ast::Type::ForType(ty) => {
+                ty.ty().is_some_and(|ty| substitute_type_in_bound(ty, param_name, replacement))
+            }
+            ast::Type::ImplTraitType(ty) => {
+                go_bounds(ty.type_bound_list(), param_name, replacement)
+            }
+            ast::Type::ParenType(ty) => {
+                ty.ty().is_some_and(|ty| substitute_type_in_bound(ty, param_name, replacement))
+            }
+            ast::Type::PathType(ty) => ty.path().is_some_and(|path| {
+                if path.as_single_name_ref().is_some_and(|name| name.text() == param_name) {
+                    ted::replace(
+                        path.syntax(),
+                        make::path_from_segments(
+                            [make::path_segment(make::name_ref(replacement))],
+                            false,
+                        )
+                        .clone_for_update()
+                        .syntax(),
+                    );
+                    return true;
+                }
+
+                any_long(
+                    path.segments()
+                        .filter_map(|segment| segment.generic_arg_list())
+                        .flat_map(|it| it.generic_args())
+                        .filter_map(|generic_arg| match generic_arg {
+                            ast::GenericArg::TypeArg(ty) => ty.ty(),
+                            _ => None,
+                        }),
+                    |ty| substitute_type_in_bound(ty, param_name, replacement),
+                )
+            }),
+            ast::Type::PtrType(ty) => {
+                ty.ty().is_some_and(|ty| substitute_type_in_bound(ty, param_name, replacement))
+            }
+            ast::Type::RefType(ty) => {
+                ty.ty().is_some_and(|ty| substitute_type_in_bound(ty, param_name, replacement))
+            }
+            ast::Type::SliceType(ty) => {
+                ty.ty().is_some_and(|ty| substitute_type_in_bound(ty, param_name, replacement))
+            }
+            ast::Type::TupleType(ty) => {
+                any_long(ty.fields(), |ty| substitute_type_in_bound(ty, param_name, replacement))
+            }
+            ast::Type::InferType(_) | ast::Type::MacroType(_) | ast::Type::NeverType(_) => false,
+        };
+
+        fn go_bounds(
+            bounds: Option<ast::TypeBoundList>,
+            param_name: &str,
+            replacement: &str,
+        ) -> bool {
+            bounds.is_some_and(|bounds| {
+                any_long(bounds.bounds(), |bound| {
+                    bound
+                        .ty()
+                        .is_some_and(|ty| substitute_type_in_bound(ty, param_name, replacement))
+                })
+            })
+        }
+
+        /// Like [`Iterator::any()`], but not short-circuiting.
+        fn any_long<I: Iterator, F: FnMut(I::Item) -> bool>(iter: I, mut f: F) -> bool {
+            let mut result = false;
+            iter.for_each(|item| result |= f(item));
+            result
+        }
+    }
+}
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 b76db2e0052..5b06de98757 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
@@ -14,12 +14,12 @@ use syntax::{
 use syntax_bridge::syntax_node_to_token_tree;
 
 use crate::{
-    builtin::quote::{dollar_crate, quote},
+    builtin::quote::{dollar_crate, quote, WithDelimiter},
     db::ExpandDatabase,
     hygiene::{span_with_call_site_ctxt, span_with_def_site_ctxt},
     name,
     span_map::SpanMap,
-    tt::{self, DelimSpan},
+    tt::{self, DelimSpan, TtElement, TtIter},
     ExpandError, ExpandResult, HirFileIdExt, Lookup as _, MacroCallId,
 };
 
@@ -36,7 +36,7 @@ macro_rules! register_builtin {
         }
 
         impl BuiltinFnLikeExpander {
-            fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::Subtree, Span) -> ExpandResult<tt::Subtree>  {
+            fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::TopSubtree, Span) -> ExpandResult<tt::TopSubtree>  {
                 match *self {
                     $( BuiltinFnLikeExpander::$kind => $expand, )*
                 }
@@ -44,7 +44,7 @@ macro_rules! register_builtin {
         }
 
         impl EagerExpander {
-            fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::Subtree, Span) -> ExpandResult<tt::Subtree>  {
+            fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::TopSubtree, Span) -> ExpandResult<tt::TopSubtree>  {
                 match *self {
                     $( EagerExpander::$e_kind => $e_expand, )*
                 }
@@ -66,9 +66,9 @@ impl BuiltinFnLikeExpander {
         &self,
         db: &dyn ExpandDatabase,
         id: MacroCallId,
-        tt: &tt::Subtree,
+        tt: &tt::TopSubtree,
         span: Span,
-    ) -> ExpandResult<tt::Subtree> {
+    ) -> ExpandResult<tt::TopSubtree> {
         let span = span_with_def_site_ctxt(db, span, id);
         self.expander()(db, id, tt, span)
     }
@@ -83,9 +83,9 @@ impl EagerExpander {
         &self,
         db: &dyn ExpandDatabase,
         id: MacroCallId,
-        tt: &tt::Subtree,
+        tt: &tt::TopSubtree,
         span: Span,
-    ) -> ExpandResult<tt::Subtree> {
+    ) -> ExpandResult<tt::TopSubtree> {
         let span = span_with_def_site_ctxt(db, span, id);
         self.expander()(db, id, tt, span)
     }
@@ -146,24 +146,16 @@ register_builtin! {
     (option_env, OptionEnv) => option_env_expand
 }
 
-fn mk_pound(span: Span) -> tt::Subtree {
-    crate::builtin::quote::IntoTt::to_subtree(
-        vec![crate::tt::Leaf::Punct(crate::tt::Punct {
-            char: '#',
-            spacing: crate::tt::Spacing::Alone,
-            span,
-        })
-        .into()],
-        span,
-    )
+fn mk_pound(span: Span) -> tt::Leaf {
+    crate::tt::Leaf::Punct(crate::tt::Punct { char: '#', spacing: crate::tt::Spacing::Alone, span })
 }
 
 fn module_path_expand(
     _db: &dyn ExpandDatabase,
     _id: MacroCallId,
-    _tt: &tt::Subtree,
+    _tt: &tt::TopSubtree,
     span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
     // Just return a dummy result.
     ExpandResult::ok(quote! {span =>
          "module::path"
@@ -173,48 +165,48 @@ fn module_path_expand(
 fn line_expand(
     _db: &dyn ExpandDatabase,
     _id: MacroCallId,
-    _tt: &tt::Subtree,
+    _tt: &tt::TopSubtree,
     span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
     // dummy implementation for type-checking purposes
     // Note that `line!` and `column!` will never be implemented properly, as they are by definition
     // not incremental
-    ExpandResult::ok(tt::Subtree {
-        delimiter: tt::Delimiter::invisible_spanned(span),
-        token_trees: Box::new([tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
+    ExpandResult::ok(tt::TopSubtree::invisible_from_leaves(
+        span,
+        [tt::Leaf::Literal(tt::Literal {
             symbol: sym::INTEGER_0.clone(),
             span,
             kind: tt::LitKind::Integer,
             suffix: Some(sym::u32.clone()),
-        }))]),
-    })
+        })],
+    ))
 }
 
 fn log_syntax_expand(
     _db: &dyn ExpandDatabase,
     _id: MacroCallId,
-    _tt: &tt::Subtree,
+    _tt: &tt::TopSubtree,
     span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
     ExpandResult::ok(quote! {span =>})
 }
 
 fn trace_macros_expand(
     _db: &dyn ExpandDatabase,
     _id: MacroCallId,
-    _tt: &tt::Subtree,
+    _tt: &tt::TopSubtree,
     span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
     ExpandResult::ok(quote! {span =>})
 }
 
 fn stringify_expand(
     _db: &dyn ExpandDatabase,
     _id: MacroCallId,
-    tt: &tt::Subtree,
+    tt: &tt::TopSubtree,
     span: Span,
-) -> ExpandResult<tt::Subtree> {
-    let pretty = ::tt::pretty(&tt.token_trees);
+) -> ExpandResult<tt::TopSubtree> {
+    let pretty = ::tt::pretty(tt.token_trees().flat_tokens());
 
     let expanded = quote! {span =>
         #pretty
@@ -226,39 +218,35 @@ fn stringify_expand(
 fn assert_expand(
     db: &dyn ExpandDatabase,
     id: MacroCallId,
-    tt: &tt::Subtree,
+    tt: &tt::TopSubtree,
     span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
     let call_site_span = span_with_call_site_ctxt(db, span, id);
 
-    let mut iter = ::tt::iter::TtIter::new(tt);
+    let mut iter = tt.iter();
 
     let cond = expect_fragment(
         &mut iter,
         parser::PrefixEntryPoint::Expr,
         db.crate_graph()[id.lookup(db).krate].edition,
-        tt::DelimSpan { open: tt.delimiter.open, close: tt.delimiter.close },
+        tt.top_subtree().delimiter.delim_span(),
     );
     _ = iter.expect_char(',');
-    let rest = iter.as_slice();
+    let rest = iter.remaining();
 
     let dollar_crate = dollar_crate(span);
-    let expanded = match cond.value {
-        Some(cond) => {
-            let panic_args = rest.iter().cloned();
-            let mac = if use_panic_2021(db, span) {
-                quote! {call_site_span => #dollar_crate::panic::panic_2021!(##panic_args) }
-            } else {
-                quote! {call_site_span => #dollar_crate::panic!(##panic_args) }
-            };
-            quote! {call_site_span =>{
-                if !(#cond) {
-                    #mac;
-                }
-            }}
-        }
-        None => quote! {call_site_span =>{}},
+    let panic_args = rest.iter();
+    let mac = if use_panic_2021(db, span) {
+        quote! {call_site_span => #dollar_crate::panic::panic_2021!(##panic_args) }
+    } else {
+        quote! {call_site_span => #dollar_crate::panic!(##panic_args) }
     };
+    let value = cond.value;
+    let expanded = quote! {call_site_span =>{
+        if !(#value) {
+            #mac;
+        }
+    }};
 
     match cond.err {
         Some(err) => ExpandResult::new(expanded, err.into()),
@@ -269,9 +257,9 @@ fn assert_expand(
 fn file_expand(
     _db: &dyn ExpandDatabase,
     _id: MacroCallId,
-    _tt: &tt::Subtree,
+    _tt: &tt::TopSubtree,
     span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
     // FIXME: RA purposefully lacks knowledge of absolute file names
     // so just return "".
     let file_name = "file";
@@ -286,12 +274,12 @@ fn file_expand(
 fn format_args_expand(
     _db: &dyn ExpandDatabase,
     _id: MacroCallId,
-    tt: &tt::Subtree,
+    tt: &tt::TopSubtree,
     span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
     let pound = mk_pound(span);
     let mut tt = tt.clone();
-    tt.delimiter.kind = tt::DelimiterKind::Parenthesis;
+    tt.top_subtree_delimiter_mut().kind = tt::DelimiterKind::Parenthesis;
     ExpandResult::ok(quote! {span =>
         builtin #pound format_args #tt
     })
@@ -300,17 +288,17 @@ fn format_args_expand(
 fn format_args_nl_expand(
     _db: &dyn ExpandDatabase,
     _id: MacroCallId,
-    tt: &tt::Subtree,
+    tt: &tt::TopSubtree,
     span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
     let pound = mk_pound(span);
     let mut tt = tt.clone();
-    tt.delimiter.kind = tt::DelimiterKind::Parenthesis;
+    tt.top_subtree_delimiter_mut().kind = tt::DelimiterKind::Parenthesis;
     if let Some(tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
         symbol: text,
         kind: tt::LitKind::Str,
         ..
-    }))) = tt.token_trees.first_mut()
+    }))) = tt.0.get_mut(1)
     {
         *text = Symbol::intern(&format_smolstr!("{}\\n", text.as_str()));
     }
@@ -322,11 +310,11 @@ fn format_args_nl_expand(
 fn asm_expand(
     _db: &dyn ExpandDatabase,
     _id: MacroCallId,
-    tt: &tt::Subtree,
+    tt: &tt::TopSubtree,
     span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
     let mut tt = tt.clone();
-    tt.delimiter.kind = tt::DelimiterKind::Parenthesis;
+    tt.top_subtree_delimiter_mut().kind = tt::DelimiterKind::Parenthesis;
     let pound = mk_pound(span);
     let expanded = quote! {span =>
         builtin #pound asm #tt
@@ -337,9 +325,9 @@ fn asm_expand(
 fn cfg_expand(
     db: &dyn ExpandDatabase,
     id: MacroCallId,
-    tt: &tt::Subtree,
+    tt: &tt::TopSubtree,
     span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
     let loc = db.lookup_intern_macro_call(id);
     let expr = CfgExpr::parse(tt);
     let enabled = db.crate_graph()[loc.krate].cfg_options.check(&expr) != Some(false);
@@ -350,9 +338,9 @@ fn cfg_expand(
 fn panic_expand(
     db: &dyn ExpandDatabase,
     id: MacroCallId,
-    tt: &tt::Subtree,
+    tt: &tt::TopSubtree,
     span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
     let dollar_crate = dollar_crate(span);
     let call_site_span = span_with_call_site_ctxt(db, span, id);
 
@@ -362,19 +350,18 @@ fn panic_expand(
         sym::panic_2015.clone()
     };
 
-    // Expand to a macro call `$crate::panic::panic_{edition}`
-    let mut call = quote!(call_site_span =>#dollar_crate::panic::#mac!);
-
     // Pass the original arguments
-    let mut subtree = tt.clone();
-    subtree.delimiter = tt::Delimiter {
-        open: call_site_span,
-        close: call_site_span,
-        kind: tt::DelimiterKind::Parenthesis,
+    let subtree = WithDelimiter {
+        delimiter: tt::Delimiter {
+            open: call_site_span,
+            close: call_site_span,
+            kind: tt::DelimiterKind::Parenthesis,
+        },
+        token_trees: tt.token_trees(),
     };
 
-    // FIXME(slow): quote! have a way to expand to builder to make this a vec!
-    call.push(tt::TokenTree::Subtree(subtree));
+    // Expand to a macro call `$crate::panic::panic_{edition}`
+    let call = quote!(call_site_span =>#dollar_crate::panic::#mac! #subtree);
 
     ExpandResult::ok(call)
 }
@@ -382,9 +369,9 @@ fn panic_expand(
 fn unreachable_expand(
     db: &dyn ExpandDatabase,
     id: MacroCallId,
-    tt: &tt::Subtree,
+    tt: &tt::TopSubtree,
     span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
     let dollar_crate = dollar_crate(span);
     let call_site_span = span_with_call_site_ctxt(db, span, id);
 
@@ -394,19 +381,16 @@ fn unreachable_expand(
         sym::unreachable_2015.clone()
     };
 
-    // Expand to a macro call `$crate::panic::panic_{edition}`
-    let mut call = quote!(call_site_span =>#dollar_crate::panic::#mac!);
-
     // Pass the original arguments
     let mut subtree = tt.clone();
-    subtree.delimiter = tt::Delimiter {
+    *subtree.top_subtree_delimiter_mut() = tt::Delimiter {
         open: call_site_span,
         close: call_site_span,
         kind: tt::DelimiterKind::Parenthesis,
     };
 
-    // FIXME(slow): quote! have a way to expand to builder to make this a vec!
-    call.push(tt::TokenTree::Subtree(subtree));
+    // Expand to a macro call `$crate::panic::panic_{edition}`
+    let call = quote!(call_site_span =>#dollar_crate::panic::#mac! #subtree);
 
     ExpandResult::ok(call)
 }
@@ -436,11 +420,11 @@ fn use_panic_2021(db: &dyn ExpandDatabase, span: Span) -> bool {
 fn compile_error_expand(
     _db: &dyn ExpandDatabase,
     _id: MacroCallId,
-    tt: &tt::Subtree,
+    tt: &tt::TopSubtree,
     span: Span,
-) -> ExpandResult<tt::Subtree> {
-    let err = match &*tt.token_trees {
-        [tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
+) -> ExpandResult<tt::TopSubtree> {
+    let err = match &*tt.0 {
+        [_, tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
             symbol: text,
             span: _,
             kind: tt::LitKind::Str | tt::LitKind::StrRaw(_),
@@ -455,9 +439,9 @@ fn compile_error_expand(
 fn concat_expand(
     _db: &dyn ExpandDatabase,
     _arg_id: MacroCallId,
-    tt: &tt::Subtree,
+    tt: &tt::TopSubtree,
     call_site: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
     let mut err = None;
     let mut text = String::new();
     let mut span: Option<Span> = None;
@@ -466,19 +450,19 @@ fn concat_expand(
         Some(_) => (),
         None => span = Some(s),
     };
-    for (i, mut t) in tt.token_trees.iter().enumerate() {
+    for (i, mut t) in tt.iter().enumerate() {
         // FIXME: hack on top of a hack: `$e:expr` captures get surrounded in parentheses
         // to ensure the right parsing order, so skip the parentheses here. Ideally we'd
         // implement rustc's model. cc https://github.com/rust-lang/rust-analyzer/pull/10623
-        if let tt::TokenTree::Subtree(tt::Subtree { delimiter: delim, token_trees }) = t {
-            if let [tt] = &**token_trees {
-                if delim.kind == tt::DelimiterKind::Parenthesis {
-                    t = tt;
+        if let TtElement::Subtree(subtree, subtree_iter) = &t {
+            if let [tt::TokenTree::Leaf(tt)] = subtree_iter.remaining().flat_tokens() {
+                if subtree.delimiter.kind == tt::DelimiterKind::Parenthesis {
+                    t = TtElement::Leaf(tt);
                 }
             }
         }
         match t {
-            tt::TokenTree::Leaf(tt::Leaf::Literal(it)) if i % 2 == 0 => {
+            TtElement::Leaf(tt::Leaf::Literal(it)) if i % 2 == 0 => {
                 // concat works with string and char literals, so remove any quotes.
                 // It also works with integer, float and boolean literals, so just use the rest
                 // as-is.
@@ -511,28 +495,28 @@ fn concat_expand(
                 }
             }
             // handle boolean literals
-            tt::TokenTree::Leaf(tt::Leaf::Ident(id))
+            TtElement::Leaf(tt::Leaf::Ident(id))
                 if i % 2 == 0 && (id.sym == sym::true_ || id.sym == sym::false_) =>
             {
                 text.push_str(id.sym.as_str());
                 record_span(id.span);
             }
-            tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
+            TtElement::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
             _ => {
                 err.get_or_insert(ExpandError::other(call_site, "unexpected token"));
             }
         }
     }
-    let span = span.unwrap_or(tt.delimiter.open);
+    let span = span.unwrap_or_else(|| tt.top_subtree().delimiter.open);
     ExpandResult { value: quote!(span =>#text), err }
 }
 
 fn concat_bytes_expand(
     _db: &dyn ExpandDatabase,
     _arg_id: MacroCallId,
-    tt: &tt::Subtree,
+    tt: &tt::TopSubtree,
     call_site: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
     let mut bytes = String::new();
     let mut err = None;
     let mut span: Option<Span> = None;
@@ -541,9 +525,9 @@ fn concat_bytes_expand(
         Some(_) => (),
         None => span = Some(s),
     };
-    for (i, t) in tt.token_trees.iter().enumerate() {
+    for (i, t) in tt.iter().enumerate() {
         match t {
-            tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
+            TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
                 symbol: text,
                 span,
                 kind,
@@ -570,10 +554,12 @@ fn concat_bytes_expand(
                     }
                 }
             }
-            tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
-            tt::TokenTree::Subtree(tree) if tree.delimiter.kind == tt::DelimiterKind::Bracket => {
+            TtElement::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
+            TtElement::Subtree(tree, tree_iter)
+                if tree.delimiter.kind == tt::DelimiterKind::Bracket =>
+            {
                 if let Err(e) =
-                    concat_bytes_expand_subtree(tree, &mut bytes, &mut record_span, call_site)
+                    concat_bytes_expand_subtree(tree_iter, &mut bytes, &mut record_span, call_site)
                 {
                     err.get_or_insert(e);
                     break;
@@ -585,31 +571,30 @@ fn concat_bytes_expand(
             }
         }
     }
-    let span = span.unwrap_or(tt.delimiter.open);
+    let span = span.unwrap_or(tt.top_subtree().delimiter.open);
     ExpandResult {
-        value: tt::Subtree {
-            delimiter: tt::Delimiter::invisible_spanned(span),
-            token_trees: vec![tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
+        value: tt::TopSubtree::invisible_from_leaves(
+            span,
+            [tt::Leaf::Literal(tt::Literal {
                 symbol: Symbol::intern(&bytes),
                 span,
                 kind: tt::LitKind::ByteStr,
                 suffix: None,
-            }))]
-            .into(),
-        },
+            })],
+        ),
         err,
     }
 }
 
 fn concat_bytes_expand_subtree(
-    tree: &tt::Subtree,
+    tree_iter: TtIter<'_>,
     bytes: &mut String,
     mut record_span: impl FnMut(Span),
     err_span: Span,
 ) -> Result<(), ExpandError> {
-    for (ti, tt) in tree.token_trees.iter().enumerate() {
+    for (ti, tt) in tree_iter.enumerate() {
         match tt {
-            tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
+            TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
                 symbol: text,
                 span,
                 kind: tt::LitKind::Byte,
@@ -620,7 +605,7 @@ fn concat_bytes_expand_subtree(
                 }
                 record_span(*span);
             }
-            tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
+            TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
                 symbol: text,
                 span,
                 kind: tt::LitKind::Integer,
@@ -631,7 +616,7 @@ fn concat_bytes_expand_subtree(
                     bytes.extend(b.escape_ascii().filter_map(|it| char::from_u32(it as u32)));
                 }
             }
-            tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if ti % 2 == 1 && punct.char == ',' => (),
+            TtElement::Leaf(tt::Leaf::Punct(punct)) if ti % 2 == 1 && punct.char == ',' => (),
             _ => {
                 return Err(ExpandError::other(err_span, "unexpected token"));
             }
@@ -643,17 +628,17 @@ fn concat_bytes_expand_subtree(
 fn concat_idents_expand(
     _db: &dyn ExpandDatabase,
     _arg_id: MacroCallId,
-    tt: &tt::Subtree,
+    tt: &tt::TopSubtree,
     span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
     let mut err = None;
     let mut ident = String::new();
-    for (i, t) in tt.token_trees.iter().enumerate() {
+    for (i, t) in tt.iter().enumerate() {
         match t {
-            tt::TokenTree::Leaf(tt::Leaf::Ident(id)) => {
+            TtElement::Leaf(tt::Leaf::Ident(id)) => {
                 ident.push_str(id.sym.as_str());
             }
-            tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
+            TtElement::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (),
             _ => {
                 err.get_or_insert(ExpandError::other(span, "unexpected token"));
             }
@@ -685,18 +670,19 @@ fn relative_file(
     }
 }
 
-fn parse_string(tt: &tt::Subtree) -> Result<(Symbol, Span), ExpandError> {
-    tt.token_trees
-        .first()
-        .ok_or(tt.delimiter.open.cover(tt.delimiter.close))
+fn parse_string(tt: &tt::TopSubtree) -> Result<(Symbol, Span), ExpandError> {
+    let delimiter = tt.top_subtree().delimiter;
+    tt.iter()
+        .next()
+        .ok_or(delimiter.open.cover(delimiter.close))
         .and_then(|tt| match tt {
-            tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
+            TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
                 symbol: text,
                 span,
                 kind: tt::LitKind::Str,
                 suffix: _,
             })) => Ok((unescape_str(text), *span)),
-            tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
+            TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
                 symbol: text,
                 span,
                 kind: tt::LitKind::StrRaw(_),
@@ -705,26 +691,30 @@ fn parse_string(tt: &tt::Subtree) -> Result<(Symbol, Span), ExpandError> {
             // FIXME: We wrap expression fragments in parentheses which can break this expectation
             // here
             // Remove this once we handle none delims correctly
-            tt::TokenTree::Subtree(tt) if tt.delimiter.kind == DelimiterKind::Parenthesis => {
-                tt.token_trees.first().and_then(|tt| match tt {
-                    tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
-                        symbol: text,
-                        span,
-                        kind: tt::LitKind::Str,
-                        suffix: _,
-                    })) => Some((unescape_str(text), *span)),
-                    tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
-                        symbol: text,
-                        span,
-                        kind: tt::LitKind::StrRaw(_),
-                        suffix: _,
-                    })) => Some((text.clone(), *span)),
-                    _ => None,
-                })
+            TtElement::Subtree(tt, mut tt_iter)
+                if tt.delimiter.kind == DelimiterKind::Parenthesis =>
+            {
+                tt_iter
+                    .next()
+                    .and_then(|tt| match tt {
+                        TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
+                            symbol: text,
+                            span,
+                            kind: tt::LitKind::Str,
+                            suffix: _,
+                        })) => Some((unescape_str(text), *span)),
+                        TtElement::Leaf(tt::Leaf::Literal(tt::Literal {
+                            symbol: text,
+                            span,
+                            kind: tt::LitKind::StrRaw(_),
+                            suffix: _,
+                        })) => Some((text.clone(), *span)),
+                        _ => None,
+                    })
+                    .ok_or(delimiter.open.cover(delimiter.close))
             }
-            .ok_or(tt.delimiter.open.cover(tt.delimiter.close)),
-            ::tt::TokenTree::Leaf(l) => Err(*l.span()),
-            ::tt::TokenTree::Subtree(tt) => Err(tt.delimiter.open.cover(tt.delimiter.close)),
+            TtElement::Leaf(l) => Err(*l.span()),
+            TtElement::Subtree(tt, _) => Err(tt.delimiter.open.cover(tt.delimiter.close)),
         })
         .map_err(|span| ExpandError::other(span, "expected string literal"))
 }
@@ -732,13 +722,16 @@ fn parse_string(tt: &tt::Subtree) -> Result<(Symbol, Span), ExpandError> {
 fn include_expand(
     db: &dyn ExpandDatabase,
     arg_id: MacroCallId,
-    tt: &tt::Subtree,
+    tt: &tt::TopSubtree,
     span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
     let file_id = match include_input_to_file_id(db, arg_id, tt) {
         Ok(it) => it,
         Err(e) => {
-            return ExpandResult::new(tt::Subtree::empty(DelimSpan { open: span, close: span }), e)
+            return ExpandResult::new(
+                tt::TopSubtree::empty(DelimSpan { open: span, close: span }),
+                e,
+            )
         }
     };
     let span_map = db.real_span_map(file_id);
@@ -754,7 +747,7 @@ fn include_expand(
 pub fn include_input_to_file_id(
     db: &dyn ExpandDatabase,
     arg_id: MacroCallId,
-    arg: &tt::Subtree,
+    arg: &tt::TopSubtree,
 ) -> Result<EditionedFileId, ExpandError> {
     let (s, span) = parse_string(arg)?;
     relative_file(db, arg_id, s.as_str(), false, span)
@@ -763,32 +756,35 @@ pub fn include_input_to_file_id(
 fn include_bytes_expand(
     _db: &dyn ExpandDatabase,
     _arg_id: MacroCallId,
-    _tt: &tt::Subtree,
+    _tt: &tt::TopSubtree,
     span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
     // FIXME: actually read the file here if the user asked for macro expansion
-    let res = tt::Subtree {
-        delimiter: tt::Delimiter::invisible_spanned(span),
-        token_trees: Box::new([tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
+    let res = tt::TopSubtree::invisible_from_leaves(
+        span,
+        [tt::Leaf::Literal(tt::Literal {
             symbol: Symbol::empty(),
             span,
             kind: tt::LitKind::ByteStrRaw(1),
             suffix: None,
-        }))]),
-    };
+        })],
+    );
     ExpandResult::ok(res)
 }
 
 fn include_str_expand(
     db: &dyn ExpandDatabase,
     arg_id: MacroCallId,
-    tt: &tt::Subtree,
+    tt: &tt::TopSubtree,
     span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
     let (path, span) = match parse_string(tt) {
         Ok(it) => it,
         Err(e) => {
-            return ExpandResult::new(tt::Subtree::empty(DelimSpan { open: span, close: span }), e)
+            return ExpandResult::new(
+                tt::TopSubtree::empty(DelimSpan { open: span, close: span }),
+                e,
+            )
         }
     };
 
@@ -817,13 +813,16 @@ fn get_env_inner(db: &dyn ExpandDatabase, arg_id: MacroCallId, key: &Symbol) ->
 fn env_expand(
     db: &dyn ExpandDatabase,
     arg_id: MacroCallId,
-    tt: &tt::Subtree,
+    tt: &tt::TopSubtree,
     span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
     let (key, span) = match parse_string(tt) {
         Ok(it) => it,
         Err(e) => {
-            return ExpandResult::new(tt::Subtree::empty(DelimSpan { open: span, close: span }), e)
+            return ExpandResult::new(
+                tt::TopSubtree::empty(DelimSpan { open: span, close: span }),
+                e,
+            )
         }
     };
 
@@ -852,14 +851,14 @@ fn env_expand(
 fn option_env_expand(
     db: &dyn ExpandDatabase,
     arg_id: MacroCallId,
-    tt: &tt::Subtree,
+    tt: &tt::TopSubtree,
     call_site: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
     let (key, span) = match parse_string(tt) {
         Ok(it) => it,
         Err(e) => {
             return ExpandResult::new(
-                tt::Subtree::empty(DelimSpan { open: call_site, close: call_site }),
+                tt::TopSubtree::empty(DelimSpan { open: call_site, close: call_site }),
                 e,
             )
         }
@@ -879,11 +878,11 @@ fn option_env_expand(
 fn quote_expand(
     _db: &dyn ExpandDatabase,
     _arg_id: MacroCallId,
-    _tt: &tt::Subtree,
+    _tt: &tt::TopSubtree,
     span: Span,
-) -> ExpandResult<tt::Subtree> {
+) -> ExpandResult<tt::TopSubtree> {
     ExpandResult::new(
-        tt::Subtree::empty(tt::DelimSpan { open: span, close: span }),
+        tt::TopSubtree::empty(tt::DelimSpan { open: span, close: span }),
         ExpandError::other(span, "quote! is not implemented"),
     )
 }
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs
index 418d8d9660b..6c1abc26203 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin/quote.rs
@@ -6,7 +6,7 @@ use span::Span;
 use syntax::ToSmolStr;
 use tt::IdentIsRaw;
 
-use crate::name::Name;
+use crate::{name::Name, tt::TopSubtreeBuilder};
 
 pub(crate) fn dollar_crate(span: Span) -> tt::Ident<Span> {
     tt::Ident { sym: sym::dollar_crate.clone(), span, is_raw: tt::IdentIsRaw::No }
@@ -20,119 +20,93 @@ pub(crate) fn dollar_crate(span: Span) -> tt::Ident<Span> {
 #[doc(hidden)]
 #[macro_export]
 macro_rules! quote_impl__ {
-    ($span:ident) => {
-        Vec::<$crate::tt::TokenTree>::new()
-    };
+    ($span:ident $builder:ident) => {};
 
-    ( @SUBTREE($span:ident) $delim:ident $($tt:tt)* ) => {
+    ( @SUBTREE($span:ident $builder:ident) $delim:ident $($tt:tt)* ) => {
         {
-            let children = $crate::builtin::quote::__quote!($span $($tt)*);
-            $crate::tt::Subtree {
-                delimiter: $crate::tt::Delimiter {
-                    kind: $crate::tt::DelimiterKind::$delim,
-                    open: $span,
-                    close: $span,
-                },
-                token_trees: $crate::builtin::quote::IntoTt::to_tokens(children).into_boxed_slice(),
-            }
+            $builder.open($crate::tt::DelimiterKind::$delim, $span);
+            $crate::builtin::quote::__quote!($span $builder  $($tt)*);
+            $builder.close($span);
         }
     };
 
-    ( @PUNCT($span:ident) $first:literal ) => {
-        {
-            vec![
-                $crate::tt::Leaf::Punct($crate::tt::Punct {
-                    char: $first,
-                    spacing: $crate::tt::Spacing::Alone,
-                    span: $span,
-                }).into()
-            ]
-        }
+    ( @PUNCT($span:ident $builder:ident) $first:literal ) => {
+        $builder.push(
+            $crate::tt::Leaf::Punct($crate::tt::Punct {
+                char: $first,
+                spacing: $crate::tt::Spacing::Alone,
+                span: $span,
+            })
+        );
     };
 
-    ( @PUNCT($span:ident) $first:literal, $sec:literal ) => {
-        {
-            vec![
-                $crate::tt::Leaf::Punct($crate::tt::Punct {
-                    char: $first,
-                    spacing: $crate::tt::Spacing::Joint,
-                    span: $span,
-                }).into(),
-                $crate::tt::Leaf::Punct($crate::tt::Punct {
-                    char: $sec,
-                    spacing: $crate::tt::Spacing::Alone,
-                    span: $span,
-                }).into()
-            ]
-        }
+    ( @PUNCT($span:ident $builder:ident) $first:literal, $sec:literal ) => {
+        $builder.extend([
+            $crate::tt::Leaf::Punct($crate::tt::Punct {
+                char: $first,
+                spacing: $crate::tt::Spacing::Joint,
+                span: $span,
+            }),
+            $crate::tt::Leaf::Punct($crate::tt::Punct {
+                char: $sec,
+                spacing: $crate::tt::Spacing::Alone,
+                span: $span,
+            })
+        ]);
     };
 
     // hash variable
-    ($span:ident # $first:ident $($tail:tt)* ) => {
-        {
-            let token = $crate::builtin::quote::ToTokenTree::to_token($first, $span);
-            let mut tokens = vec![token.into()];
-            let mut tail_tokens = $crate::builtin::quote::IntoTt::to_tokens($crate::builtin::quote::__quote!($span $($tail)*));
-            tokens.append(&mut tail_tokens);
-            tokens
-        }
+    ($span:ident $builder:ident # $first:ident $($tail:tt)* ) => {
+        $crate::builtin::quote::ToTokenTree::to_tokens($first, $span, $builder);
+        $crate::builtin::quote::__quote!($span $builder $($tail)*);
     };
 
-    ($span:ident ## $first:ident $($tail:tt)* ) => {
-        {
-            let mut tokens = $first.into_iter().map(|it| $crate::builtin::quote::ToTokenTree::to_token(it, $span)).collect::<Vec<crate::tt::TokenTree>>();
-            let mut tail_tokens = $crate::builtin::quote::IntoTt::to_tokens($crate::builtin::quote::__quote!($span $($tail)*));
-            tokens.append(&mut tail_tokens);
-            tokens
-        }
-    };
+    ($span:ident $builder:ident ## $first:ident $($tail:tt)* ) => {{
+        ::std::iter::IntoIterator::into_iter($first).for_each(|it| $crate::builtin::quote::ToTokenTree::to_tokens(it, $span, $builder));
+        $crate::builtin::quote::__quote!($span $builder $($tail)*);
+    }};
 
     // Brace
-    ($span:ident  { $($tt:tt)* } ) => { $crate::builtin::quote::__quote!(@SUBTREE($span) Brace $($tt)*) };
+    ($span:ident $builder:ident { $($tt:tt)* } ) => { $crate::builtin::quote::__quote!(@SUBTREE($span $builder) Brace $($tt)*) };
     // Bracket
-    ($span:ident  [ $($tt:tt)* ] ) => { $crate::builtin::quote::__quote!(@SUBTREE($span) Bracket $($tt)*) };
+    ($span:ident $builder:ident [ $($tt:tt)* ] ) => { $crate::builtin::quote::__quote!(@SUBTREE($span $builder) Bracket $($tt)*) };
     // Parenthesis
-    ($span:ident  ( $($tt:tt)* ) ) => { $crate::builtin::quote::__quote!(@SUBTREE($span) Parenthesis $($tt)*) };
+    ($span:ident $builder:ident ( $($tt:tt)* ) ) => { $crate::builtin::quote::__quote!(@SUBTREE($span $builder) Parenthesis $($tt)*) };
 
     // Literal
-    ($span:ident $tt:literal ) => { vec![$crate::builtin::quote::ToTokenTree::to_token($tt, $span).into()] };
+    ($span:ident $builder:ident $tt:literal ) => { $crate::builtin::quote::ToTokenTree::to_tokens($tt, $span, $builder) };
     // Ident
-    ($span:ident $tt:ident ) => {
-        vec![ {
+    ($span:ident $builder:ident $tt:ident ) => {
+        $builder.push(
             $crate::tt::Leaf::Ident($crate::tt::Ident {
                 sym: intern::Symbol::intern(stringify!($tt)),
                 span: $span,
                 is_raw: tt::IdentIsRaw::No,
-            }).into()
-        }]
+            })
+        );
     };
 
     // Puncts
     // FIXME: Not all puncts are handled
-    ($span:ident -> ) => {$crate::builtin::quote::__quote!(@PUNCT($span) '-', '>')};
-    ($span:ident => ) => {$crate::builtin::quote::__quote!(@PUNCT($span) '=', '>')};
-    ($span:ident & ) => {$crate::builtin::quote::__quote!(@PUNCT($span) '&')};
-    ($span:ident , ) => {$crate::builtin::quote::__quote!(@PUNCT($span) ',')};
-    ($span:ident : ) => {$crate::builtin::quote::__quote!(@PUNCT($span) ':')};
-    ($span:ident ; ) => {$crate::builtin::quote::__quote!(@PUNCT($span) ';')};
-    ($span:ident :: ) => {$crate::builtin::quote::__quote!(@PUNCT($span) ':', ':')};
-    ($span:ident . ) => {$crate::builtin::quote::__quote!(@PUNCT($span) '.')};
-    ($span:ident < ) => {$crate::builtin::quote::__quote!(@PUNCT($span) '<')};
-    ($span:ident > ) => {$crate::builtin::quote::__quote!(@PUNCT($span) '>')};
-    ($span:ident ! ) => {$crate::builtin::quote::__quote!(@PUNCT($span) '!')};
-    ($span:ident # ) => {$crate::builtin::quote::__quote!(@PUNCT($span) '#')};
-    ($span:ident $ ) => {$crate::builtin::quote::__quote!(@PUNCT($span) '$')};
-    ($span:ident * ) => {$crate::builtin::quote::__quote!(@PUNCT($span) '*')};
-
-    ($span:ident $first:tt $($tail:tt)+ ) => {
-        {
-            let mut tokens = $crate::builtin::quote::IntoTt::to_tokens($crate::builtin::quote::__quote!($span $first ));
-            let mut tail_tokens = $crate::builtin::quote::IntoTt::to_tokens($crate::builtin::quote::__quote!($span $($tail)*));
-
-            tokens.append(&mut tail_tokens);
-            tokens
-        }
-    };
+    ($span:ident $builder:ident -> ) => {$crate::builtin::quote::__quote!(@PUNCT($span $builder) '-', '>')};
+    ($span:ident $builder:ident => ) => {$crate::builtin::quote::__quote!(@PUNCT($span $builder) '=', '>')};
+    ($span:ident $builder:ident & ) => {$crate::builtin::quote::__quote!(@PUNCT($span $builder) '&')};
+    ($span:ident $builder:ident , ) => {$crate::builtin::quote::__quote!(@PUNCT($span $builder) ',')};
+    ($span:ident $builder:ident : ) => {$crate::builtin::quote::__quote!(@PUNCT($span $builder) ':')};
+    ($span:ident $builder:ident ; ) => {$crate::builtin::quote::__quote!(@PUNCT($span $builder) ';')};
+    ($span:ident $builder:ident :: ) => {$crate::builtin::quote::__quote!(@PUNCT($span $builder) ':', ':')};
+    ($span:ident $builder:ident . ) => {$crate::builtin::quote::__quote!(@PUNCT($span $builder) '.')};
+    ($span:ident $builder:ident < ) => {$crate::builtin::quote::__quote!(@PUNCT($span $builder) '<')};
+    ($span:ident $builder:ident > ) => {$crate::builtin::quote::__quote!(@PUNCT($span $builder) '>')};
+    ($span:ident $builder:ident ! ) => {$crate::builtin::quote::__quote!(@PUNCT($span $builder) '!')};
+    ($span:ident $builder:ident # ) => {$crate::builtin::quote::__quote!(@PUNCT($span $builder) '#')};
+    ($span:ident $builder:ident $ ) => {$crate::builtin::quote::__quote!(@PUNCT($span $builder) '$')};
+    ($span:ident $builder:ident * ) => {$crate::builtin::quote::__quote!(@PUNCT($span $builder) '*')};
+
+    ($span:ident $builder:ident $first:tt $($tail:tt)+ ) => {{
+        $crate::builtin::quote::__quote!($span $builder $first);
+        $crate::builtin::quote::__quote!($span $builder $($tail)*);
+    }};
 }
 pub use quote_impl__ as __quote;
 
@@ -141,52 +115,68 @@ pub use quote_impl__ as __quote;
 #[macro_export]
 macro_rules! quote {
     ($span:ident=> $($tt:tt)* ) => {
-        $crate::builtin::quote::IntoTt::to_subtree($crate::builtin::quote::__quote!($span $($tt)*), $span)
+        {
+            let mut builder = $crate::tt::TopSubtreeBuilder::new($crate::tt::Delimiter {
+                kind: $crate::tt::DelimiterKind::Invisible,
+                open: $span,
+                close: $span,
+            });
+            #[allow(unused)]
+            let builder_ref = &mut builder;
+            $crate::builtin::quote::__quote!($span builder_ref $($tt)*);
+            builder.build_skip_top_subtree()
+        }
     }
 }
 pub(super) use quote;
 
-pub trait IntoTt {
-    fn to_subtree(self, span: Span) -> crate::tt::Subtree;
-    fn to_tokens(self) -> Vec<crate::tt::TokenTree>;
+pub trait ToTokenTree {
+    fn to_tokens(self, span: Span, builder: &mut TopSubtreeBuilder);
 }
 
-impl IntoTt for Vec<crate::tt::TokenTree> {
-    fn to_subtree(self, span: Span) -> crate::tt::Subtree {
-        crate::tt::Subtree {
-            delimiter: crate::tt::Delimiter::invisible_spanned(span),
-            token_trees: self.into_boxed_slice(),
-        }
-    }
-
-    fn to_tokens(self) -> Vec<crate::tt::TokenTree> {
-        self
-    }
+/// Wraps `TokenTreesView` with a delimiter (a subtree, but without allocating).
+pub struct WithDelimiter<'a> {
+    pub delimiter: crate::tt::Delimiter,
+    pub token_trees: crate::tt::TokenTreesView<'a>,
 }
 
-impl IntoTt for crate::tt::Subtree {
-    fn to_subtree(self, _: Span) -> crate::tt::Subtree {
-        self
+impl ToTokenTree for WithDelimiter<'_> {
+    fn to_tokens(self, span: Span, builder: &mut TopSubtreeBuilder) {
+        builder.open(self.delimiter.kind, self.delimiter.open);
+        self.token_trees.to_tokens(span, builder);
+        builder.close(self.delimiter.close);
     }
+}
 
-    fn to_tokens(self) -> Vec<crate::tt::TokenTree> {
-        vec![crate::tt::TokenTree::Subtree(self)]
+impl ToTokenTree for crate::tt::TokenTreesView<'_> {
+    fn to_tokens(self, _: Span, builder: &mut TopSubtreeBuilder) {
+        builder.extend_with_tt(self);
     }
 }
 
-pub trait ToTokenTree {
-    fn to_token(self, span: Span) -> crate::tt::TokenTree;
+impl ToTokenTree for crate::tt::SubtreeView<'_> {
+    fn to_tokens(self, _: Span, builder: &mut TopSubtreeBuilder) {
+        builder.extend_with_tt(self.as_token_trees());
+    }
 }
 
-impl ToTokenTree for crate::tt::TokenTree {
-    fn to_token(self, _: Span) -> crate::tt::TokenTree {
-        self
+impl ToTokenTree for crate::tt::TopSubtree {
+    fn to_tokens(self, _: Span, builder: &mut TopSubtreeBuilder) {
+        builder.extend_tt_dangerous(self.0);
     }
 }
 
-impl ToTokenTree for crate::tt::Subtree {
-    fn to_token(self, _: Span) -> crate::tt::TokenTree {
-        self.into()
+impl ToTokenTree for crate::tt::TtElement<'_> {
+    fn to_tokens(self, _: Span, builder: &mut TopSubtreeBuilder) {
+        match self {
+            crate::tt::TtElement::Leaf(leaf) => builder.push(leaf.clone()),
+            crate::tt::TtElement::Subtree(subtree, subtree_iter) => {
+                builder.extend_tt_dangerous(
+                    std::iter::once(crate::tt::TokenTree::Subtree(subtree.clone()))
+                        .chain(subtree_iter.remaining().flat_tokens().iter().cloned()),
+                );
+            }
+        }
     }
 }
 
@@ -194,18 +184,17 @@ macro_rules! impl_to_to_tokentrees {
     ($($span:ident: $ty:ty => $this:ident $im:block;)*) => {
         $(
             impl ToTokenTree for $ty {
-                fn to_token($this, $span: Span) -> crate::tt::TokenTree {
+                fn to_tokens($this, $span: Span, builder: &mut TopSubtreeBuilder) {
                     let leaf: crate::tt::Leaf = $im.into();
-                    leaf.into()
+                    builder.push(leaf);
                 }
             }
         )*
     }
 }
-
 impl<T: ToTokenTree + Clone> ToTokenTree for &T {
-    fn to_token(self, span: Span) -> crate::tt::TokenTree {
-        self.clone().to_token(span)
+    fn to_tokens(self, span: Span, builder: &mut TopSubtreeBuilder) {
+        self.clone().to_tokens(span, builder);
     }
 }
 
@@ -316,18 +305,15 @@ mod tests {
         // }
         let struct_name = mk_ident("Foo");
         let fields = [mk_ident("name"), mk_ident("id")];
-        let fields = fields
-            .iter()
-            .flat_map(|it| quote!(DUMMY =>#it: self.#it.clone(), ).token_trees.into_vec());
-
-        let list = crate::tt::Subtree {
-            delimiter: crate::tt::Delimiter {
-                kind: crate::tt::DelimiterKind::Brace,
-                open: DUMMY,
-                close: DUMMY,
-            },
-            token_trees: fields.collect(),
-        };
+        let fields = fields.iter().map(|it| quote!(DUMMY =>#it: self.#it.clone(), ));
+
+        let mut builder = tt::TopSubtreeBuilder::new(crate::tt::Delimiter {
+            kind: crate::tt::DelimiterKind::Brace,
+            open: DUMMY,
+            close: DUMMY,
+        });
+        fields.for_each(|field| builder.extend_with_tt(field.view().as_token_trees()));
+        let list = builder.build();
 
         let quoted = quote! {DUMMY =>
             impl Clone for #struct_name {
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 fa400378f3a..f4e80ef9e26 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
@@ -28,7 +28,7 @@ use crate::{
     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);
+type MacroArgResult = (Arc<tt::TopSubtree>, 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
@@ -123,7 +123,7 @@ pub trait ExpandDatabase: SourceDatabase {
     /// proc macros, since they are not deterministic in general, and
     /// non-determinism breaks salsa in a very, very, very bad way.
     /// @edwin0cheng heroically debugged this once! See #4315 for details
-    fn expand_proc_macro(&self, call: MacroCallId) -> ExpandResult<Arc<tt::Subtree>>;
+    fn expand_proc_macro(&self, call: MacroCallId) -> ExpandResult<Arc<tt::TopSubtree>>;
     /// Retrieves the span to be used for a proc-macro expansions spans.
     /// This is a firewall query as it requires parsing the file, which we don't want proc-macros to
     /// directly depend on as that would cause to frequent invalidations, mainly because of the
@@ -251,7 +251,7 @@ pub fn expand_speculative(
                         span,
                         DocCommentDesugarMode::ProcMacro,
                     );
-                    tree.delimiter = tt::Delimiter::invisible_spanned(span);
+                    *tree.top_subtree_delimiter_mut() = tt::Delimiter::invisible_spanned(span);
 
                     Some(tree)
                 }
@@ -266,7 +266,7 @@ pub fn expand_speculative(
     let mut speculative_expansion = match loc.def.kind {
         MacroDefKind::ProcMacro(ast, expander, _) => {
             let span = db.proc_macro_span(ast);
-            tt.delimiter = tt::Delimiter::invisible_spanned(span);
+            *tt.top_subtree_delimiter_mut() = tt::Delimiter::invisible_spanned(span);
             expander.expand(
                 db,
                 loc.def.krate,
@@ -429,10 +429,10 @@ fn macro_arg(db: &dyn ExpandDatabase, id: MacroCallId) -> MacroArgResult {
 
             let dummy_tt = |kind| {
                 (
-                    Arc::new(tt::Subtree {
-                        delimiter: tt::Delimiter { open: span, close: span, kind },
-                        token_trees: Box::default(),
-                    }),
+                    Arc::new(tt::TopSubtree::from_token_trees(
+                        tt::Delimiter { open: span, close: span, kind },
+                        tt::TokenTreesView::new(&[]),
+                    )),
                     SyntaxFixupUndoInfo::default(),
                     span,
                 )
@@ -479,7 +479,7 @@ fn macro_arg(db: &dyn ExpandDatabase, id: MacroCallId) -> MacroArgResult {
             );
             if loc.def.is_proc_macro() {
                 // proc macros expect their inputs without parentheses, MBEs expect it with them included
-                tt.delimiter.kind = tt::DelimiterKind::Invisible;
+                tt.top_subtree_delimiter_mut().kind = tt::DelimiterKind::Invisible;
             }
             return (Arc::new(tt), SyntaxFixupUndoInfo::NONE, span);
         }
@@ -537,7 +537,7 @@ fn macro_arg(db: &dyn ExpandDatabase, id: MacroCallId) -> MacroArgResult {
 
     if loc.def.is_proc_macro() {
         // proc macros expect their inputs without parentheses, MBEs expect it with them included
-        tt.delimiter.kind = tt::DelimiterKind::Invisible;
+        tt.top_subtree_delimiter_mut().kind = tt::DelimiterKind::Invisible;
     }
 
     (Arc::new(tt), undo_info, span)
@@ -592,7 +592,7 @@ fn macro_expand(
     db: &dyn ExpandDatabase,
     macro_call_id: MacroCallId,
     loc: MacroCallLoc,
-) -> ExpandResult<(CowArc<tt::Subtree>, MatchedArmIndex)> {
+) -> ExpandResult<(CowArc<tt::TopSubtree>, MatchedArmIndex)> {
     let _p = tracing::info_span!("macro_expand").entered();
 
     let (ExpandResult { value: (tt, matched_arm), err }, span) = match loc.def.kind {
@@ -655,12 +655,7 @@ fn macro_expand(
         // Set a hard limit for the expanded tt
         if let Err(value) = check_tt_count(&tt) {
             return value
-                .map(|()| {
-                    CowArc::Owned(tt::Subtree {
-                        delimiter: tt::Delimiter::invisible_spanned(span),
-                        token_trees: Box::new([]),
-                    })
-                })
+                .map(|()| CowArc::Owned(tt::TopSubtree::empty(tt::DelimSpan::from_single(span))))
                 .zip_val(matched_arm);
         }
     }
@@ -679,7 +674,10 @@ fn proc_macro_span(db: &dyn ExpandDatabase, ast: AstId<ast::Fn>) -> Span {
     span_map.span_for_range(range)
 }
 
-fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt::Subtree>> {
+fn expand_proc_macro(
+    db: &dyn ExpandDatabase,
+    id: MacroCallId,
+) -> ExpandResult<Arc<tt::TopSubtree>> {
     let loc = db.lookup_intern_macro_call(id);
     let (macro_arg, undo_info, span) = db.macro_arg_considering_derives(id, &loc.kind);
 
@@ -709,12 +707,7 @@ fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<A
 
     // Set a hard limit for the expanded tt
     if let Err(value) = check_tt_count(&tt) {
-        return value.map(|()| {
-            Arc::new(tt::Subtree {
-                delimiter: tt::Delimiter::invisible_spanned(span),
-                token_trees: Box::new([]),
-            })
-        });
+        return value.map(|()| Arc::new(tt::TopSubtree::empty(tt::DelimSpan::from_single(span))));
     }
 
     fixup::reverse_fixups(&mut tt, &undo_info);
@@ -723,7 +716,7 @@ fn expand_proc_macro(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<A
 }
 
 fn token_tree_to_syntax_node(
-    tt: &tt::Subtree,
+    tt: &tt::TopSubtree,
     expand_to: ExpandTo,
     edition: parser::Edition,
 ) -> (Parse<SyntaxNode>, ExpansionSpanMap) {
@@ -737,7 +730,8 @@ fn token_tree_to_syntax_node(
     syntax_bridge::token_tree_to_syntax_node(tt, entry_point, edition)
 }
 
-fn check_tt_count(tt: &tt::Subtree) -> Result<(), ExpandResult<()>> {
+fn check_tt_count(tt: &tt::TopSubtree) -> Result<(), ExpandResult<()>> {
+    let tt = tt.top_subtree();
     let count = tt.count();
     if TOKEN_LIMIT.check(count).is_err() {
         Err(ExpandResult {
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 86dd4aef090..d1c39f32ca3 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/declarative.rs
@@ -26,14 +26,14 @@ impl DeclarativeMacroExpander {
     pub fn expand(
         &self,
         db: &dyn ExpandDatabase,
-        tt: tt::Subtree,
+        tt: tt::TopSubtree,
         call_id: MacroCallId,
         span: Span,
-    ) -> ExpandResult<(tt::Subtree, Option<u32>)> {
+    ) -> ExpandResult<(tt::TopSubtree, Option<u32>)> {
         let loc = db.lookup_intern_macro_call(call_id);
         match self.mac.err() {
             Some(_) => ExpandResult::new(
-                (tt::Subtree::empty(tt::DelimSpan { open: span, close: span }), None),
+                (tt::TopSubtree::empty(tt::DelimSpan { open: span, close: span }), None),
                 ExpandError::new(span, ExpandErrorKind::MacroDefinition),
             ),
             None => self
@@ -50,13 +50,13 @@ impl DeclarativeMacroExpander {
 
     pub fn expand_unhygienic(
         &self,
-        tt: tt::Subtree,
+        tt: tt::TopSubtree,
         call_site: Span,
         def_site_edition: Edition,
-    ) -> ExpandResult<tt::Subtree> {
+    ) -> ExpandResult<tt::TopSubtree> {
         match self.mac.err() {
             Some(_) => ExpandResult::new(
-                tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
+                tt::TopSubtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
                 ExpandError::new(call_site, ExpandErrorKind::MacroDefinition),
             ),
             None => self
@@ -78,7 +78,7 @@ impl DeclarativeMacroExpander {
         let transparency = |node| {
             // ... would be nice to have the item tree here
             let attrs = RawAttrs::new(db, node, map.as_ref()).filter(db, def_crate);
-            match &*attrs
+            match attrs
                 .iter()
                 .find(|it| {
                     it.path
@@ -87,7 +87,8 @@ impl DeclarativeMacroExpander {
                         .unwrap_or(false)
                 })?
                 .token_tree_value()?
-                .token_trees
+                .token_trees()
+                .flat_tokens()
             {
                 [tt::TokenTree::Leaf(tt::Leaf::Ident(i)), ..] => match &i.sym {
                     s if *s == sym::transparent => Some(Transparency::Transparent),
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs b/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs
index 1dadfe2ba99..f476d1b564c 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs
@@ -89,7 +89,7 @@ pub fn expand_eager_macro_input(
         DocCommentDesugarMode::Mbe,
     );
 
-    subtree.delimiter.kind = crate::tt::DelimiterKind::Invisible;
+    subtree.top_subtree_delimiter_mut().kind = crate::tt::DelimiterKind::Invisible;
 
     let loc = MacroCallLoc {
         def,
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs b/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs
index 0af29681a13..3d2d52a0afe 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/fixup.rs
@@ -3,7 +3,6 @@
 
 use intern::sym;
 use rustc_hash::{FxHashMap, FxHashSet};
-use smallvec::SmallVec;
 use span::{
     ErasedFileAstId, Span, SpanAnchor, SyntaxContextId, FIXUP_ERASED_FILE_AST_ID_MARKER,
     ROOT_ERASED_FILE_AST_ID,
@@ -19,7 +18,7 @@ use tt::Spacing;
 
 use crate::{
     span_map::SpanMapRef,
-    tt::{Ident, Leaf, Punct, Subtree},
+    tt::{self, Ident, Leaf, Punct, TopSubtree},
 };
 
 /// The result of calculating fixes for a syntax node -- a bunch of changes
@@ -36,7 +35,7 @@ pub(crate) struct SyntaxFixups {
 #[derive(Clone, Debug, Default, PartialEq, Eq)]
 pub struct SyntaxFixupUndoInfo {
     // FIXME: ThinArc<[Subtree]>
-    original: Option<Arc<Box<[Subtree]>>>,
+    original: Option<Arc<Box<[TopSubtree]>>>,
 }
 
 impl SyntaxFixupUndoInfo {
@@ -110,7 +109,7 @@ pub(crate) fn fixup_syntax(
                     }
                 },
                 ast::ExprStmt(it) => {
-                    let needs_semi = it.semicolon_token().is_none() && it.expr().map_or(false, |e| e.syntax().kind() != SyntaxKind::BLOCK_EXPR);
+                    let needs_semi = it.semicolon_token().is_none() && it.expr().is_some_and(|e| e.syntax().kind() != SyntaxKind::BLOCK_EXPR);
                     if needs_semi {
                         append.insert(node.clone().into(), vec![
                             Leaf::Punct(Punct {
@@ -369,68 +368,126 @@ fn has_error_to_handle(node: &SyntaxNode) -> bool {
     has_error(node) || node.children().any(|c| !can_handle_error(&c) && has_error_to_handle(&c))
 }
 
-pub(crate) fn reverse_fixups(tt: &mut Subtree, undo_info: &SyntaxFixupUndoInfo) {
+pub(crate) fn reverse_fixups(tt: &mut TopSubtree, undo_info: &SyntaxFixupUndoInfo) {
     let Some(undo_info) = undo_info.original.as_deref() else { return };
     let undo_info = &**undo_info;
+    let delimiter = tt.top_subtree_delimiter_mut();
     #[allow(deprecated)]
     if never!(
-        tt.delimiter.close.anchor.ast_id == FIXUP_DUMMY_AST_ID
-            || tt.delimiter.open.anchor.ast_id == FIXUP_DUMMY_AST_ID
+        delimiter.close.anchor.ast_id == FIXUP_DUMMY_AST_ID
+            || delimiter.open.anchor.ast_id == FIXUP_DUMMY_AST_ID
     ) {
         let span = |file_id| Span {
             range: TextRange::empty(TextSize::new(0)),
             anchor: SpanAnchor { file_id, ast_id: ROOT_ERASED_FILE_AST_ID },
             ctx: SyntaxContextId::ROOT,
         };
-        tt.delimiter.open = span(tt.delimiter.open.anchor.file_id);
-        tt.delimiter.close = span(tt.delimiter.close.anchor.file_id);
+        delimiter.open = span(delimiter.open.anchor.file_id);
+        delimiter.close = span(delimiter.close.anchor.file_id);
     }
     reverse_fixups_(tt, undo_info);
 }
 
-fn reverse_fixups_(tt: &mut Subtree, undo_info: &[Subtree]) {
-    let tts = std::mem::take(&mut tt.token_trees).into_vec();
-    tt.token_trees = tts
-        .into_iter()
-        // delete all fake nodes
-        .filter(|tt| match tt {
-            tt::TokenTree::Leaf(leaf) => {
-                let span = leaf.span();
-                let is_real_leaf = span.anchor.ast_id != FIXUP_DUMMY_AST_ID;
-                let is_replaced_node = span.range.end() == FIXUP_DUMMY_RANGE_END;
-                is_real_leaf || is_replaced_node
+#[derive(Debug)]
+enum TransformTtAction<'a> {
+    Keep,
+    ReplaceWith(tt::TokenTreesView<'a>),
+}
+
+impl TransformTtAction<'_> {
+    fn remove() -> Self {
+        Self::ReplaceWith(tt::TokenTreesView::new(&[]))
+    }
+}
+
+/// This function takes a token tree, and calls `callback` with each token tree in it.
+/// Then it does what the callback says: keeps the tt or replaces it with a (possibly empty)
+/// tts view.
+fn transform_tt<'a, 'b>(
+    tt: &'a mut Vec<tt::TokenTree>,
+    mut callback: impl FnMut(&mut tt::TokenTree) -> TransformTtAction<'b>,
+) {
+    // We need to keep a stack of the currently open subtrees, because we need to update
+    // them if we change the number of items in them.
+    let mut subtrees_stack = Vec::new();
+    let mut i = 0;
+    while i < tt.len() {
+        'pop_finished_subtrees: while let Some(&subtree_idx) = subtrees_stack.last() {
+            let tt::TokenTree::Subtree(subtree) = &tt[subtree_idx] else {
+                unreachable!("non-subtree on subtrees stack");
+            };
+            if i >= subtree_idx + 1 + subtree.usize_len() {
+                subtrees_stack.pop();
+            } else {
+                break 'pop_finished_subtrees;
             }
-            tt::TokenTree::Subtree(_) => true,
-        })
-        .flat_map(|tt| match tt {
-            tt::TokenTree::Subtree(mut tt) => {
-                if tt.delimiter.close.anchor.ast_id == FIXUP_DUMMY_AST_ID
-                    || tt.delimiter.open.anchor.ast_id == FIXUP_DUMMY_AST_ID
-                {
-                    // Even though fixup never creates subtrees with fixup spans, the old proc-macro server
-                    // might copy them if the proc-macro asks for it, so we need to filter those out
-                    // here as well.
-                    return SmallVec::new_const();
+        }
+
+        let action = callback(&mut tt[i]);
+        match action {
+            TransformTtAction::Keep => {
+                // This cannot be shared with the replaced case, because then we may push the same subtree
+                // twice, and will update it twice which will lead to errors.
+                if let tt::TokenTree::Subtree(_) = &tt[i] {
+                    subtrees_stack.push(i);
                 }
-                reverse_fixups_(&mut tt, undo_info);
-                SmallVec::from_const([tt.into()])
+
+                i += 1;
             }
-            tt::TokenTree::Leaf(leaf) => {
-                if leaf.span().anchor.ast_id == FIXUP_DUMMY_AST_ID {
-                    // we have a fake node here, we need to replace it again with the original
-                    let original = undo_info[u32::from(leaf.span().range.start()) as usize].clone();
-                    if original.delimiter.kind == tt::DelimiterKind::Invisible {
-                        SmallVec::from(original.token_trees.into_vec())
-                    } else {
-                        SmallVec::from_const([original.into()])
-                    }
-                } else {
-                    // just a normal leaf
-                    SmallVec::from_const([leaf.into()])
+            TransformTtAction::ReplaceWith(replacement) => {
+                let old_len = 1 + match &tt[i] {
+                    tt::TokenTree::Leaf(_) => 0,
+                    tt::TokenTree::Subtree(subtree) => subtree.usize_len(),
+                };
+                let len_diff = replacement.len() as i64 - old_len as i64;
+                tt.splice(i..i + old_len, replacement.flat_tokens().iter().cloned());
+                // `+1` for the loop.
+                i = i.checked_add_signed(len_diff as isize + 1).unwrap();
+
+                for &subtree_idx in &subtrees_stack {
+                    let tt::TokenTree::Subtree(subtree) = &mut tt[subtree_idx] else {
+                        unreachable!("non-subtree on subtrees stack");
+                    };
+                    subtree.len = (i64::from(subtree.len) + len_diff).try_into().unwrap();
                 }
             }
-        })
-        .collect();
+        }
+    }
+}
+
+fn reverse_fixups_(tt: &mut TopSubtree, undo_info: &[TopSubtree]) {
+    let mut tts = std::mem::take(&mut tt.0).into_vec();
+    transform_tt(&mut tts, |tt| match tt {
+        tt::TokenTree::Leaf(leaf) => {
+            let span = leaf.span();
+            let is_real_leaf = span.anchor.ast_id != FIXUP_DUMMY_AST_ID;
+            let is_replaced_node = span.range.end() == FIXUP_DUMMY_RANGE_END;
+            if !is_real_leaf && !is_replaced_node {
+                return TransformTtAction::remove();
+            }
+
+            if !is_real_leaf {
+                // we have a fake node here, we need to replace it again with the original
+                let original = &undo_info[u32::from(leaf.span().range.start()) as usize];
+                TransformTtAction::ReplaceWith(original.view().strip_invisible())
+            } else {
+                // just a normal leaf
+                TransformTtAction::Keep
+            }
+        }
+        tt::TokenTree::Subtree(tt) => {
+            if tt.delimiter.close.anchor.ast_id == FIXUP_DUMMY_AST_ID
+                || tt.delimiter.open.anchor.ast_id == FIXUP_DUMMY_AST_ID
+            {
+                // Even though fixup never creates subtrees with fixup spans, the old proc-macro server
+                // might copy them if the proc-macro asks for it, so we need to filter those out
+                // here as well.
+                return TransformTtAction::remove();
+            }
+            TransformTtAction::Keep
+        }
+    });
+    tt.0 = tts.into_boxed_slice();
 }
 
 #[cfg(test)]
@@ -458,16 +515,18 @@ mod tests {
         }
     }
 
-    fn check_subtree_eq(a: &tt::Subtree, b: &tt::Subtree) -> bool {
-        a.delimiter.kind == b.delimiter.kind
-            && a.token_trees.len() == b.token_trees.len()
-            && a.token_trees.iter().zip(b.token_trees.iter()).all(|(a, b)| check_tt_eq(a, b))
+    fn check_subtree_eq(a: &tt::TopSubtree, b: &tt::TopSubtree) -> bool {
+        let a = a.view().as_token_trees().flat_tokens();
+        let b = b.view().as_token_trees().flat_tokens();
+        a.len() == b.len() && std::iter::zip(a, b).all(|(a, b)| check_tt_eq(a, b))
     }
 
     fn check_tt_eq(a: &tt::TokenTree, b: &tt::TokenTree) -> bool {
         match (a, b) {
             (tt::TokenTree::Leaf(a), tt::TokenTree::Leaf(b)) => check_leaf_eq(a, b),
-            (tt::TokenTree::Subtree(a), tt::TokenTree::Subtree(b)) => check_subtree_eq(a, b),
+            (tt::TokenTree::Subtree(a), tt::TokenTree::Subtree(b)) => {
+                a.delimiter.kind == b.delimiter.kind
+            }
             _ => false,
         }
     }
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 5aafe6db527..a0c4c125db4 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
@@ -70,12 +70,17 @@ pub mod tt {
     pub type Delimiter = ::tt::Delimiter<Span>;
     pub type DelimSpan = ::tt::DelimSpan<Span>;
     pub type Subtree = ::tt::Subtree<Span>;
-    pub type SubtreeBuilder = ::tt::SubtreeBuilder<Span>;
     pub type Leaf = ::tt::Leaf<Span>;
     pub type Literal = ::tt::Literal<Span>;
     pub type Punct = ::tt::Punct<Span>;
     pub type Ident = ::tt::Ident<Span>;
     pub type TokenTree = ::tt::TokenTree<Span>;
+    pub type TopSubtree = ::tt::TopSubtree<Span>;
+    pub type TopSubtreeBuilder = ::tt::TopSubtreeBuilder<Span>;
+    pub type TokenTreesView<'a> = ::tt::TokenTreesView<'a, Span>;
+    pub type SubtreeView<'a> = ::tt::SubtreeView<'a, Span>;
+    pub type TtElement<'a> = ::tt::iter::TtElement<'a, Span>;
+    pub type TtIter<'a> = ::tt::iter::TtIter<'a, Span>;
 }
 
 #[macro_export]
@@ -284,7 +289,7 @@ impl MacroDefKind {
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct EagerCallInfo {
     /// The expanded argument of the eager macro.
-    arg: Arc<tt::Subtree>,
+    arg: Arc<tt::TopSubtree>,
     /// 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>,
@@ -320,7 +325,7 @@ pub enum MacroCallKind {
         ast_id: AstId<ast::Item>,
         // FIXME: This shouldn't be here, we can derive this from `invoc_attr_index`
         // but we need to fix the `cfg_attr` handling first.
-        attr_args: Option<Arc<tt::Subtree>>,
+        attr_args: Option<Arc<tt::TopSubtree>>,
         /// Syntactical index of the invoking `#[attribute]`.
         ///
         /// Outer attributes are counted first, then inner attributes. This does not support
@@ -1044,7 +1049,7 @@ impl ExpandTo {
         if parent.kind() == MACRO_EXPR
             && parent
                 .parent()
-                .map_or(false, |p| matches!(p.kind(), EXPR_STMT | STMT_LIST | MACRO_STMTS))
+                .is_some_and(|p| matches!(p.kind(), EXPR_STMT | STMT_LIST | MACRO_STMTS))
         {
             return ExpandTo::Statements;
         }
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 dcf2af39979..7ecf5219873 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
@@ -58,7 +58,7 @@ impl ModPath {
         convert_path(db, path, span_for_range)
     }
 
-    pub fn from_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree]) -> Option<ModPath> {
+    pub fn from_tt(db: &dyn ExpandDatabase, tt: tt::TokenTreesView<'_>) -> Option<ModPath> {
         convert_path_tt(db, tt)
     }
 
@@ -315,10 +315,10 @@ fn convert_path(
     Some(mod_path)
 }
 
-fn convert_path_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree]) -> Option<ModPath> {
+fn convert_path_tt(db: &dyn ExpandDatabase, tt: tt::TokenTreesView<'_>) -> Option<ModPath> {
     let mut leaves = tt.iter().filter_map(|tt| match tt {
-        tt::TokenTree::Leaf(leaf) => Some(leaf),
-        tt::TokenTree::Subtree(_) => None,
+        tt::TtElement::Leaf(leaf) => Some(leaf),
+        tt::TtElement::Subtree(..) => None,
     });
     let mut segments = smallvec::smallvec![];
     let kind = match leaves.next()? {
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 fe09f0307c9..07808fea85b 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,14 +23,14 @@ pub trait ProcMacroExpander: fmt::Debug + Send + Sync + RefUnwindSafe {
     /// [`ProcMacroKind::Attr`]), environment variables, and span information.
     fn expand(
         &self,
-        subtree: &tt::Subtree,
-        attrs: Option<&tt::Subtree>,
+        subtree: &tt::TopSubtree,
+        attrs: Option<&tt::TopSubtree>,
         env: &Env,
         def_site: Span,
         call_site: Span,
         mixed_site: Span,
         current_dir: Option<String>,
-    ) -> Result<tt::Subtree, ProcMacroExpansionError>;
+    ) -> Result<tt::TopSubtree, ProcMacroExpansionError>;
 }
 
 #[derive(Debug)]
@@ -201,23 +201,23 @@ impl CustomProcMacroExpander {
         db: &dyn ExpandDatabase,
         def_crate: CrateId,
         calling_crate: CrateId,
-        tt: &tt::Subtree,
-        attr_arg: Option<&tt::Subtree>,
+        tt: &tt::TopSubtree,
+        attr_arg: Option<&tt::TopSubtree>,
         def_site: Span,
         call_site: Span,
         mixed_site: Span,
-    ) -> ExpandResult<tt::Subtree> {
+    ) -> ExpandResult<tt::TopSubtree> {
         match self.proc_macro_id {
             Self::PROC_MACRO_ATTR_DISABLED => ExpandResult::new(
-                tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
+                tt::TopSubtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
                 ExpandError::new(call_site, ExpandErrorKind::ProcMacroAttrExpansionDisabled),
             ),
             Self::MISSING_EXPANDER => ExpandResult::new(
-                tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
+                tt::TopSubtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
                 ExpandError::new(call_site, ExpandErrorKind::MissingProcMacroExpander(def_crate)),
             ),
             Self::DISABLED_ID => ExpandResult::new(
-                tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
+                tt::TopSubtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
                 ExpandError::new(call_site, ExpandErrorKind::MacroDisabled),
             ),
             id => {
@@ -226,7 +226,10 @@ impl CustomProcMacroExpander {
                     Ok(proc_macro) => proc_macro,
                     Err(e) => {
                         return ExpandResult::new(
-                            tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
+                            tt::TopSubtree::empty(tt::DelimSpan {
+                                open: call_site,
+                                close: call_site,
+                            }),
                             e,
                         )
                     }
@@ -260,7 +263,10 @@ impl CustomProcMacroExpander {
                         }
                         ProcMacroExpansionError::System(text)
                         | ProcMacroExpansionError::Panic(text) => ExpandResult::new(
-                            tt::Subtree::empty(tt::DelimSpan { open: call_site, close: call_site }),
+                            tt::TopSubtree::empty(tt::DelimSpan {
+                                open: call_site,
+                                close: call_site,
+                            }),
                             ExpandError::new(
                                 call_site,
                                 ExpandErrorKind::ProcMacroPanic(text.into_boxed_str()),
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 55d0edd5e0c..9f01f1eb259 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
@@ -13,7 +13,7 @@ use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait};
 
 use base_db::CrateId;
 use hir_def::{
-    data::adt::StructFlags,
+    data::{adt::StructFlags, TraitFlags},
     hir::Movability,
     lang_item::{LangItem, LangItemTarget},
     AssocItemId, BlockId, CallableDefId, GenericDefId, HasModule, ItemContainerId, Lookup,
@@ -675,13 +675,13 @@ pub(crate) fn trait_datum_query(
     let generic_params = generics(db.upcast(), trait_.into());
     let bound_vars = generic_params.bound_vars_subst(db, DebruijnIndex::INNERMOST);
     let flags = rust_ir::TraitFlags {
-        auto: trait_data.is_auto,
+        auto: trait_data.flags.contains(TraitFlags::IS_AUTO),
         upstream: trait_.lookup(db.upcast()).container.krate() != krate,
         non_enumerable: true,
         coinductive: false, // only relevant for Chalk testing
         // FIXME: set these flags correctly
         marker: false,
-        fundamental: trait_data.fundamental,
+        fundamental: trait_data.flags.contains(TraitFlags::IS_FUNDAMENTAL),
     };
     let where_clauses = convert_where_clauses(db, trait_.into(), &bound_vars);
     let associated_ty_ids = trait_data.associated_types().map(to_assoc_type_id).collect();
@@ -950,11 +950,18 @@ pub(crate) fn fn_def_datum_query(db: &dyn HirDatabase, fn_def_id: FnDefId) -> Ar
 
 pub(crate) fn fn_def_variance_query(db: &dyn HirDatabase, fn_def_id: FnDefId) -> Variances {
     let callable_def: CallableDefId = from_chalk(db, fn_def_id);
-    let generic_params =
-        generics(db.upcast(), GenericDefId::from_callable(db.upcast(), callable_def));
     Variances::from_iter(
         Interner,
-        std::iter::repeat(chalk_ir::Variance::Invariant).take(generic_params.len()),
+        db.variances_of(GenericDefId::from_callable(db.upcast(), callable_def))
+            .as_deref()
+            .unwrap_or_default()
+            .iter()
+            .map(|v| match v {
+                crate::variance::Variance::Covariant => chalk_ir::Variance::Covariant,
+                crate::variance::Variance::Invariant => chalk_ir::Variance::Invariant,
+                crate::variance::Variance::Contravariant => chalk_ir::Variance::Contravariant,
+                crate::variance::Variance::Bivariant => chalk_ir::Variance::Invariant,
+            }),
     )
 }
 
@@ -962,10 +969,14 @@ pub(crate) fn adt_variance_query(
     db: &dyn HirDatabase,
     chalk_ir::AdtId(adt_id): AdtId,
 ) -> Variances {
-    let generic_params = generics(db.upcast(), adt_id.into());
     Variances::from_iter(
         Interner,
-        std::iter::repeat(chalk_ir::Variance::Invariant).take(generic_params.len()),
+        db.variances_of(adt_id.into()).as_deref().unwrap_or_default().iter().map(|v| match v {
+            crate::variance::Variance::Covariant => chalk_ir::Variance::Covariant,
+            crate::variance::Variance::Invariant => chalk_ir::Variance::Invariant,
+            crate::variance::Variance::Contravariant => chalk_ir::Variance::Contravariant,
+            crate::variance::Variance::Bivariant => chalk_ir::Variance::Invariant,
+        }),
     )
 }
 
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 302558162ac..51c178b90d7 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
@@ -443,13 +443,25 @@ impl ProjectionTyExt for ProjectionTy {
 }
 
 pub trait DynTyExt {
-    fn principal(&self) -> Option<&TraitRef>;
+    fn principal(&self) -> Option<Binders<Binders<&TraitRef>>>;
+    fn principal_id(&self) -> Option<chalk_ir::TraitId<Interner>>;
 }
 
 impl DynTyExt for DynTy {
-    fn principal(&self) -> Option<&TraitRef> {
+    fn principal(&self) -> Option<Binders<Binders<&TraitRef>>> {
+        self.bounds.as_ref().filter_map(|bounds| {
+            bounds.interned().first().and_then(|b| {
+                b.as_ref().filter_map(|b| match b {
+                    crate::WhereClause::Implemented(trait_ref) => Some(trait_ref),
+                    _ => None,
+                })
+            })
+        })
+    }
+
+    fn principal_id(&self) -> Option<chalk_ir::TraitId<Interner>> {
         self.bounds.skip_binders().interned().first().and_then(|b| match b.skip_binders() {
-            crate::WhereClause::Implemented(trait_ref) => Some(trait_ref),
+            crate::WhereClause::Implemented(trait_ref) => Some(trait_ref.trait_id),
             _ => None,
         })
     }
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 6856eaa3e02..6b056826670 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
@@ -271,6 +271,10 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
     #[ra_salsa::invoke(chalk_db::adt_variance_query)]
     fn adt_variance(&self, adt_id: chalk_db::AdtId) -> chalk_db::Variances;
 
+    #[ra_salsa::invoke(crate::variance::variances_of)]
+    #[ra_salsa::cycle(crate::variance::variances_of_cycle)]
+    fn variances_of(&self, def: GenericDefId) -> Option<Arc<[crate::variance::Variance]>>;
+
     #[ra_salsa::invoke(chalk_db::associated_ty_value_query)]
     fn associated_ty_value(
         &self,
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs
index aa0c9e30be1..348f8a0f4a8 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/decl_check/case_conv.rs
@@ -49,7 +49,7 @@ fn is_camel_case(name: &str) -> bool {
     let mut fst = None;
     // start with a non-lowercase letter rather than non-uppercase
     // ones (some scripts don't have a concept of upper/lowercase)
-    name.chars().next().map_or(true, |c| !c.is_lowercase())
+    name.chars().next().is_none_or(|c| !c.is_lowercase())
         && !name.contains("__")
         && !name.chars().any(|snd| {
             let ret = match fst {
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 92404e3a10e..7f9f0c0de19 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
@@ -295,7 +295,7 @@ impl ExprValidator {
                         path,
                         self.body.expr_path_hygiene(scrutinee_expr),
                     );
-                value_or_partial.map_or(true, |v| !matches!(v, ValueNs::StaticId(_)))
+                value_or_partial.is_none_or(|v| !matches!(v, ValueNs::StaticId(_)))
             }
             Expr::Field { expr, .. } => match self.infer.type_of_expr[*expr].kind(Interner) {
                 TyKind::Adt(adt, ..)
@@ -447,7 +447,7 @@ impl ExprValidator {
                         loop {
                             let parent = top_if_expr.syntax().parent();
                             let has_parent_expr_stmt_or_stmt_list =
-                                parent.as_ref().map_or(false, |node| {
+                                parent.as_ref().is_some_and(|node| {
                                     ast::ExprStmt::can_cast(node.kind())
                                         | ast::StmtList::can_cast(node.kind())
                                 });
@@ -529,7 +529,7 @@ impl FilterMapNextChecker {
                 let is_dyn_trait = self
                     .prev_receiver_ty
                     .as_ref()
-                    .map_or(false, |it| it.strip_references().dyn_trait().is_some());
+                    .is_some_and(|it| it.strip_references().dyn_trait().is_some());
                 if *receiver_expr_id == prev_filter_map_expr_id && !is_dyn_trait {
                     return Some(());
                 }
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 5452f5c680d..2b854310a15 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
@@ -314,7 +314,7 @@ impl<'db> MatchCheckCtx<'db> {
     }
 }
 
-impl<'db> PatCx for MatchCheckCtx<'db> {
+impl PatCx for MatchCheckCtx<'_> {
     type Error = ();
     type Ty = Ty;
     type VariantIdx = EnumVariantContiguousIndex;
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 de8ce56df64..a4e052a0362 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -474,7 +474,9 @@ impl HirDisplay for ProjectionTy {
 
         let trait_ref = self.trait_ref(f.db);
         write!(f, "<")?;
-        fmt_trait_ref(f, &trait_ref, true)?;
+        trait_ref.self_type_parameter(Interner).hir_fmt(f)?;
+        write!(f, " as ")?;
+        trait_ref.hir_fmt(f)?;
         write!(
             f,
             ">::{}",
@@ -1775,32 +1777,14 @@ fn write_bounds_like_dyn_trait(
     Ok(())
 }
 
-fn fmt_trait_ref(
-    f: &mut HirFormatter<'_>,
-    tr: &TraitRef,
-    use_as: bool,
-) -> Result<(), HirDisplayError> {
-    if f.should_truncate() {
-        return write!(f, "{TYPE_HINT_TRUNCATION}");
-    }
-
-    tr.self_type_parameter(Interner).hir_fmt(f)?;
-    if use_as {
-        write!(f, " as ")?;
-    } else {
-        write!(f, ": ")?;
-    }
-    let trait_ = tr.hir_trait_id();
-    f.start_location_link(trait_.into());
-    write!(f, "{}", f.db.trait_data(trait_).name.display(f.db.upcast(), f.edition()))?;
-    f.end_location_link();
-    let substs = tr.substitution.as_slice(Interner);
-    hir_fmt_generics(f, &substs[1..], None, substs[0].ty(Interner))
-}
-
 impl HirDisplay for TraitRef {
     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
-        fmt_trait_ref(f, self, false)
+        let trait_ = self.hir_trait_id();
+        f.start_location_link(trait_.into());
+        write!(f, "{}", f.db.trait_data(trait_).name.display(f.db.upcast(), f.edition()))?;
+        f.end_location_link();
+        let substs = self.substitution.as_slice(Interner);
+        hir_fmt_generics(f, &substs[1..], None, substs[0].ty(Interner))
     }
 }
 
@@ -1811,10 +1795,17 @@ impl HirDisplay for WhereClause {
         }
 
         match self {
-            WhereClause::Implemented(trait_ref) => trait_ref.hir_fmt(f)?,
+            WhereClause::Implemented(trait_ref) => {
+                trait_ref.self_type_parameter(Interner).hir_fmt(f)?;
+                write!(f, ": ")?;
+                trait_ref.hir_fmt(f)?;
+            }
             WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
                 write!(f, "<")?;
-                fmt_trait_ref(f, &projection_ty.trait_ref(f.db), true)?;
+                let trait_ref = &projection_ty.trait_ref(f.db);
+                trait_ref.self_type_parameter(Interner).hir_fmt(f)?;
+                write!(f, " as ")?;
+                trait_ref.hir_fmt(f)?;
                 write!(f, ">::",)?;
                 let type_alias = from_assoc_type_id(projection_ty.associated_ty_id);
                 f.start_location_link(type_alias.into());
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
index fadf8aca998..6a01579bccc 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
@@ -9,8 +9,8 @@ use chalk_ir::{
 };
 use chalk_solve::rust_ir::InlineBound;
 use hir_def::{
-    lang_item::LangItem, AssocItemId, ConstId, FunctionId, GenericDefId, HasModule, TraitId,
-    TypeAliasId,
+    data::TraitFlags, lang_item::LangItem, AssocItemId, ConstId, FunctionId, GenericDefId,
+    HasModule, TraitId, TypeAliasId,
 };
 use rustc_hash::FxHashSet;
 use smallvec::SmallVec;
@@ -432,7 +432,7 @@ where
         // Allow `impl AutoTrait` predicates
         if let WhereClause::Implemented(TraitRef { trait_id, substitution }) = pred {
             let trait_data = db.trait_data(from_chalk_trait_id(*trait_id));
-            if trait_data.is_auto
+            if trait_data.flags.contains(TraitFlags::IS_AUTO)
                 && substitution
                     .as_slice(Interner)
                     .first()
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
index fe7541d2374..abbf2a4f2ef 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/generics.rs
@@ -26,14 +26,14 @@ use triomphe::Arc;
 
 use crate::{db::HirDatabase, lt_to_placeholder_idx, to_placeholder_idx, Interner, Substitution};
 
-pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
+pub fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
     let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def)));
     let params = db.generic_params(def);
     let has_trait_self_param = params.trait_self_param().is_some();
     Generics { def, params, parent_generics, has_trait_self_param }
 }
 #[derive(Clone, Debug)]
-pub(crate) struct Generics {
+pub struct Generics {
     def: GenericDefId,
     params: Arc<GenericParams>,
     parent_generics: Option<Box<Generics>>,
@@ -153,7 +153,7 @@ impl Generics {
         (parent_len, self_param, type_params, const_params, impl_trait_params, lifetime_params)
     }
 
-    pub(crate) fn type_or_const_param_idx(&self, param: TypeOrConstParamId) -> Option<usize> {
+    pub fn type_or_const_param_idx(&self, param: TypeOrConstParamId) -> Option<usize> {
         self.find_type_or_const_param(param)
     }
 
@@ -174,7 +174,7 @@ impl Generics {
         }
     }
 
-    pub(crate) fn lifetime_idx(&self, lifetime: LifetimeParamId) -> Option<usize> {
+    pub fn lifetime_idx(&self, lifetime: LifetimeParamId) -> Option<usize> {
         self.find_lifetime(lifetime)
     }
 
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 dbee5a1a919..25bb3a76de2 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
@@ -16,6 +16,7 @@
 pub(crate) mod cast;
 pub(crate) mod closure;
 mod coerce;
+mod diagnostics;
 mod expr;
 mod mutability;
 mod pat;
@@ -57,15 +58,20 @@ use crate::{
     db::HirDatabase,
     fold_tys,
     generics::Generics,
-    infer::{coerce::CoerceMany, expr::ExprIsRead, unify::InferenceTable},
-    lower::{ImplTraitLoweringMode, TyLoweringDiagnostic},
+    infer::{
+        coerce::CoerceMany,
+        diagnostics::{Diagnostics, InferenceTyLoweringContext as TyLoweringContext},
+        expr::ExprIsRead,
+        unify::InferenceTable,
+    },
+    lower::{diagnostics::TyLoweringDiagnostic, ImplTraitLoweringMode},
     mir::MirSpan,
     to_assoc_type_id,
     traits::FnTrait,
     utils::{InTypeConstIdMetadata, UnevaluatedConstEvaluatorFolder},
     AliasEq, AliasTy, Binders, ClosureId, Const, DomainGoal, GenericArg, Goal, ImplTraitId,
-    ImplTraitIdx, InEnvironment, Interner, Lifetime, OpaqueTyId, ParamLoweringMode, ProjectionTy,
-    Substitution, TraitEnvironment, Ty, TyBuilder, TyExt,
+    ImplTraitIdx, InEnvironment, Interner, Lifetime, OpaqueTyId, ParamLoweringMode,
+    PathLoweringDiagnostic, ProjectionTy, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt,
 };
 
 // This lint has a false positive here. See the link below for details.
@@ -276,6 +282,10 @@ pub enum InferenceDiagnostic {
         source: InferenceTyDiagnosticSource,
         diag: TyLoweringDiagnostic,
     },
+    PathDiagnostic {
+        node: ExprOrPatId,
+        diag: PathLoweringDiagnostic,
+    },
 }
 
 /// A mismatch between an expected and an inferred type.
@@ -442,6 +452,7 @@ pub struct InferenceResult {
     /// [`InferenceContext`] and store the tuples substitution there. This map is the reverse of
     /// that which allows us to resolve a [`TupleFieldId`]s type.
     pub tuple_field_access_types: FxHashMap<TupleId, Substitution>,
+    /// During inference this field is empty and [`InferenceContext::diagnostics`] is filled instead.
     pub diagnostics: Vec<InferenceDiagnostic>,
     pub type_of_expr: ArenaMap<ExprId, Ty>,
     /// For each pattern record the type it resolves to.
@@ -579,6 +590,8 @@ pub(crate) struct InferenceContext<'a> {
     pub(crate) db: &'a dyn HirDatabase,
     pub(crate) owner: DefWithBodyId,
     pub(crate) body: &'a Body,
+    /// Generally you should not resolve things via this resolver. Instead create a TyLoweringContext
+    /// and resolve the path via its methods. This will ensure proper error reporting.
     pub(crate) resolver: Resolver,
     generics: OnceCell<Option<Generics>>,
     table: unify::InferenceTable<'a>,
@@ -620,6 +633,8 @@ pub(crate) struct InferenceContext<'a> {
     /// comment on `InferenceContext::sort_closures`
     closure_dependencies: FxHashMap<ClosureId, Vec<ClosureId>>,
     deferred_closures: FxHashMap<ClosureId, Vec<(Ty, Ty, Vec<Ty>, ExprId)>>,
+
+    diagnostics: Diagnostics,
 }
 
 #[derive(Clone, Debug)]
@@ -701,6 +716,7 @@ impl<'a> InferenceContext<'a> {
             deferred_closures: FxHashMap::default(),
             closure_dependencies: FxHashMap::default(),
             inside_assignment: false,
+            diagnostics: Diagnostics::default(),
         }
     }
 
@@ -724,8 +740,10 @@ impl<'a> InferenceContext<'a> {
             mut result,
             mut deferred_cast_checks,
             tuple_field_accesses_rev,
+            diagnostics,
             ..
         } = self;
+        let mut diagnostics = diagnostics.finish();
         // Destructure every single field so whenever new fields are added to `InferenceResult` we
         // don't forget to handle them here.
         let InferenceResult {
@@ -733,7 +751,6 @@ impl<'a> InferenceContext<'a> {
             field_resolutions: _,
             variant_resolutions: _,
             assoc_resolutions,
-            diagnostics,
             type_of_expr,
             type_of_pat,
             type_of_binding,
@@ -752,6 +769,7 @@ impl<'a> InferenceContext<'a> {
             mutated_bindings_in_closure: _,
             tuple_field_access_types: _,
             coercion_casts,
+            diagnostics: _,
         } = &mut result;
         table.fallback_if_possible();
 
@@ -866,6 +884,9 @@ impl<'a> InferenceContext<'a> {
                     *has_errors || subst.type_parameters(Interner).any(|ty| ty.contains_unknown());
             })
             .collect();
+
+        result.diagnostics = diagnostics;
+
         result
     }
 
@@ -1238,41 +1259,28 @@ impl<'a> InferenceContext<'a> {
         self.result.type_of_binding.insert(id, ty);
     }
 
-    fn push_diagnostic(&mut self, diagnostic: InferenceDiagnostic) {
-        self.result.diagnostics.push(diagnostic);
-    }
-
-    fn push_ty_diagnostics(
-        &mut self,
-        source: InferenceTyDiagnosticSource,
-        diagnostics: Vec<TyLoweringDiagnostic>,
-    ) {
-        self.result.diagnostics.extend(
-            diagnostics.into_iter().map(|diag| InferenceDiagnostic::TyDiagnostic { source, diag }),
-        );
+    fn push_diagnostic(&self, diagnostic: InferenceDiagnostic) {
+        self.diagnostics.push(diagnostic);
     }
 
     fn with_ty_lowering<R>(
         &mut self,
         types_map: &TypesMap,
         types_source: InferenceTyDiagnosticSource,
-        f: impl FnOnce(&mut crate::lower::TyLoweringContext<'_>) -> R,
+        f: impl FnOnce(&mut TyLoweringContext<'_>) -> R,
     ) -> R {
-        let mut ctx = crate::lower::TyLoweringContext::new(
+        let mut ctx = TyLoweringContext::new(
             self.db,
             &self.resolver,
             types_map,
             self.owner.into(),
+            &self.diagnostics,
+            types_source,
         );
-        let result = f(&mut ctx);
-        self.push_ty_diagnostics(types_source, ctx.diagnostics);
-        result
+        f(&mut ctx)
     }
 
-    fn with_body_ty_lowering<R>(
-        &mut self,
-        f: impl FnOnce(&mut crate::lower::TyLoweringContext<'_>) -> R,
-    ) -> R {
+    fn with_body_ty_lowering<R>(&mut self, f: impl FnOnce(&mut TyLoweringContext<'_>) -> R) -> R {
         self.with_ty_lowering(&self.body.types, InferenceTyDiagnosticSource::Body, f)
     }
 
@@ -1451,51 +1459,55 @@ impl<'a> InferenceContext<'a> {
         }
     }
 
-    fn resolve_variant(&mut self, path: Option<&Path>, value_ns: bool) -> (Ty, Option<VariantId>) {
+    fn resolve_variant(
+        &mut self,
+        node: ExprOrPatId,
+        path: Option<&Path>,
+        value_ns: bool,
+    ) -> (Ty, Option<VariantId>) {
         let path = match path {
             Some(path) => path,
             None => return (self.err_ty(), None),
         };
-        let mut ctx = crate::lower::TyLoweringContext::new(
+        let mut ctx = TyLoweringContext::new(
             self.db,
             &self.resolver,
             &self.body.types,
             self.owner.into(),
+            &self.diagnostics,
+            InferenceTyDiagnosticSource::Body,
         );
         let (resolution, unresolved) = if value_ns {
-            match self.resolver.resolve_path_in_value_ns(self.db.upcast(), path, HygieneId::ROOT) {
-                Some(ResolveValueResult::ValueNs(value, _)) => match value {
+            let Some(res) = ctx.resolve_path_in_value_ns(path, node, HygieneId::ROOT) else {
+                return (self.err_ty(), None);
+            };
+            match res {
+                ResolveValueResult::ValueNs(value, _) => match value {
                     ValueNs::EnumVariantId(var) => {
                         let substs = ctx.substs_from_path(path, var.into(), true);
-                        self.push_ty_diagnostics(
-                            InferenceTyDiagnosticSource::Body,
-                            ctx.diagnostics,
-                        );
+                        drop(ctx);
                         let ty = self.db.ty(var.lookup(self.db.upcast()).parent.into());
                         let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
                         return (ty, Some(var.into()));
                     }
                     ValueNs::StructId(strukt) => {
                         let substs = ctx.substs_from_path(path, strukt.into(), true);
-                        self.push_ty_diagnostics(
-                            InferenceTyDiagnosticSource::Body,
-                            ctx.diagnostics,
-                        );
+                        drop(ctx);
                         let ty = self.db.ty(strukt.into());
                         let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
                         return (ty, Some(strukt.into()));
                     }
                     ValueNs::ImplSelf(impl_id) => (TypeNs::SelfType(impl_id), None),
-                    _ => return (self.err_ty(), None),
+                    _ => {
+                        drop(ctx);
+                        return (self.err_ty(), None);
+                    }
                 },
-                Some(ResolveValueResult::Partial(typens, unresolved, _)) => {
-                    (typens, Some(unresolved))
-                }
-                None => return (self.err_ty(), None),
+                ResolveValueResult::Partial(typens, unresolved, _) => (typens, Some(unresolved)),
             }
         } else {
-            match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path) {
-                Some((it, idx, _)) => (it, idx),
+            match ctx.resolve_path_in_type_ns(path, node) {
+                Some((it, idx)) => (it, idx),
                 None => return (self.err_ty(), None),
             }
         };
@@ -1506,21 +1518,21 @@ impl<'a> InferenceContext<'a> {
         return match resolution {
             TypeNs::AdtId(AdtId::StructId(strukt)) => {
                 let substs = ctx.substs_from_path(path, strukt.into(), true);
-                self.push_ty_diagnostics(InferenceTyDiagnosticSource::Body, ctx.diagnostics);
+                drop(ctx);
                 let ty = self.db.ty(strukt.into());
                 let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
                 forbid_unresolved_segments((ty, Some(strukt.into())), unresolved)
             }
             TypeNs::AdtId(AdtId::UnionId(u)) => {
                 let substs = ctx.substs_from_path(path, u.into(), true);
-                self.push_ty_diagnostics(InferenceTyDiagnosticSource::Body, ctx.diagnostics);
+                drop(ctx);
                 let ty = self.db.ty(u.into());
                 let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
                 forbid_unresolved_segments((ty, Some(u.into())), unresolved)
             }
             TypeNs::EnumVariantId(var) => {
                 let substs = ctx.substs_from_path(path, var.into(), true);
-                self.push_ty_diagnostics(InferenceTyDiagnosticSource::Body, ctx.diagnostics);
+                drop(ctx);
                 let ty = self.db.ty(var.lookup(self.db.upcast()).parent.into());
                 let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
                 forbid_unresolved_segments((ty, Some(var.into())), unresolved)
@@ -1531,6 +1543,7 @@ impl<'a> InferenceContext<'a> {
                 let mut ty = self.db.impl_self_ty(impl_id).substitute(Interner, &substs);
 
                 let Some(mut remaining_idx) = unresolved else {
+                    drop(ctx);
                     return self.resolve_variant_on_alias(ty, None, mod_path);
                 };
 
@@ -1538,6 +1551,7 @@ impl<'a> InferenceContext<'a> {
 
                 // We need to try resolving unresolved segments one by one because each may resolve
                 // to a projection, which `TyLoweringContext` cannot handle on its own.
+                let mut tried_resolving_once = false;
                 while !remaining_segments.is_empty() {
                     let resolved_segment = path.segments().get(remaining_idx - 1).unwrap();
                     let current_segment = remaining_segments.take(1);
@@ -1558,18 +1572,27 @@ impl<'a> InferenceContext<'a> {
                         }
                     }
 
+                    if tried_resolving_once {
+                        // FIXME: with `inherent_associated_types` this is allowed, but our `lower_partly_resolved_path()`
+                        // will need to be updated to err at the correct segment.
+                        //
+                        // We need to stop here because otherwise the segment index passed to `lower_partly_resolved_path()`
+                        // will be incorrect, and that can mess up error reporting.
+                        break;
+                    }
+
                     // `lower_partly_resolved_path()` returns `None` as type namespace unless
                     // `remaining_segments` is empty, which is never the case here. We don't know
                     // which namespace the new `ty` is in until normalized anyway.
                     (ty, _) = ctx.lower_partly_resolved_path(
+                        node,
                         resolution,
                         resolved_segment,
                         current_segment,
+                        (remaining_idx - 1) as u32,
                         false,
-                        &mut |_, _reason| {
-                            // FIXME: Report an error.
-                        },
                     );
+                    tried_resolving_once = true;
 
                     ty = self.table.insert_type_vars(ty);
                     ty = self.table.normalize_associated_types_in(ty);
@@ -1582,7 +1605,7 @@ impl<'a> InferenceContext<'a> {
                     remaining_idx += 1;
                     remaining_segments = remaining_segments.skip(1);
                 }
-                self.push_ty_diagnostics(InferenceTyDiagnosticSource::Body, ctx.diagnostics);
+                drop(ctx);
 
                 let variant = ty.as_adt().and_then(|(id, _)| match id {
                     AdtId::StructId(s) => Some(VariantId::StructId(s)),
@@ -1601,7 +1624,7 @@ impl<'a> InferenceContext<'a> {
                 };
                 let substs =
                     ctx.substs_from_path_segment(resolved_seg, Some(it.into()), true, None);
-                self.push_ty_diagnostics(InferenceTyDiagnosticSource::Body, ctx.diagnostics);
+                drop(ctx);
                 let ty = self.db.ty(it.into());
                 let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
index 5a251683b96..2523aba5383 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
@@ -96,8 +96,8 @@ impl InferenceContext<'_> {
                     .map(|b| b.into_value_and_skipped_binders().0);
                 self.deduce_closure_kind_from_predicate_clauses(clauses)
             }
-            TyKind::Dyn(dyn_ty) => dyn_ty.principal().and_then(|trait_ref| {
-                self.fn_trait_kind_from_trait_id(from_chalk_trait_id(trait_ref.trait_id))
+            TyKind::Dyn(dyn_ty) => dyn_ty.principal_id().and_then(|trait_id| {
+                self.fn_trait_kind_from_trait_id(from_chalk_trait_id(trait_id))
             }),
             TyKind::InferenceVar(ty, chalk_ir::TyVariableKind::General) => {
                 let clauses = self.clauses_for_self_ty(*ty);
@@ -992,7 +992,7 @@ impl InferenceContext<'_> {
                 },
             },
         }
-        if self.result.pat_adjustments.get(&p).map_or(false, |it| !it.is_empty()) {
+        if self.result.pat_adjustments.get(&p).is_some_and(|it| !it.is_empty()) {
             for_mut = BorrowKind::Mut { kind: MutBorrowKind::ClosureCapture };
         }
         self.body.walk_pats_shallow(p, |p| self.walk_pat_inner(p, update_result, for_mut));
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs
new file mode 100644
index 00000000000..032dc37899d
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/diagnostics.rs
@@ -0,0 +1,128 @@
+//! This file contains the [`Diagnostics`] type used during inference,
+//! and a wrapper around [`TyLoweringContext`] ([`InferenceTyLoweringContext`]) that replaces
+//! it and takes care of diagnostics in inference.
+
+use std::cell::RefCell;
+use std::ops::{Deref, DerefMut};
+
+use hir_def::body::HygieneId;
+use hir_def::hir::ExprOrPatId;
+use hir_def::path::{Path, PathSegment, PathSegments};
+use hir_def::resolver::{ResolveValueResult, Resolver, TypeNs};
+use hir_def::type_ref::TypesMap;
+use hir_def::TypeOwnerId;
+
+use crate::db::HirDatabase;
+use crate::{
+    InferenceDiagnostic, InferenceTyDiagnosticSource, Ty, TyLoweringContext, TyLoweringDiagnostic,
+};
+
+// Unfortunately, this struct needs to use interior mutability (but we encapsulate it)
+// because when lowering types and paths we hold a `TyLoweringContext` that holds a reference
+// to our resolver and so we cannot have mutable reference, but we really want to have
+// ability to dispatch diagnostics during this work otherwise the code becomes a complete mess.
+#[derive(Debug, Default, Clone)]
+pub(super) struct Diagnostics(RefCell<Vec<InferenceDiagnostic>>);
+
+impl Diagnostics {
+    pub(super) fn push(&self, diagnostic: InferenceDiagnostic) {
+        self.0.borrow_mut().push(diagnostic);
+    }
+
+    fn push_ty_diagnostics(
+        &self,
+        source: InferenceTyDiagnosticSource,
+        diagnostics: Vec<TyLoweringDiagnostic>,
+    ) {
+        self.0.borrow_mut().extend(
+            diagnostics.into_iter().map(|diag| InferenceDiagnostic::TyDiagnostic { source, diag }),
+        );
+    }
+
+    pub(super) fn finish(self) -> Vec<InferenceDiagnostic> {
+        self.0.into_inner()
+    }
+}
+
+pub(super) struct InferenceTyLoweringContext<'a> {
+    ctx: TyLoweringContext<'a>,
+    diagnostics: &'a Diagnostics,
+    source: InferenceTyDiagnosticSource,
+}
+
+impl<'a> InferenceTyLoweringContext<'a> {
+    pub(super) fn new(
+        db: &'a dyn HirDatabase,
+        resolver: &'a Resolver,
+        types_map: &'a TypesMap,
+        owner: TypeOwnerId,
+        diagnostics: &'a Diagnostics,
+        source: InferenceTyDiagnosticSource,
+    ) -> Self {
+        Self { ctx: TyLoweringContext::new(db, resolver, types_map, owner), diagnostics, source }
+    }
+
+    pub(super) fn resolve_path_in_type_ns(
+        &mut self,
+        path: &Path,
+        node: ExprOrPatId,
+    ) -> Option<(TypeNs, Option<usize>)> {
+        let diagnostics = self.diagnostics;
+        self.ctx.resolve_path_in_type_ns(path, &mut |_, diag| {
+            diagnostics.push(InferenceDiagnostic::PathDiagnostic { node, diag })
+        })
+    }
+
+    pub(super) fn resolve_path_in_value_ns(
+        &mut self,
+        path: &Path,
+        node: ExprOrPatId,
+        hygiene_id: HygieneId,
+    ) -> Option<ResolveValueResult> {
+        let diagnostics = self.diagnostics;
+        self.ctx.resolve_path_in_value_ns(path, hygiene_id, &mut |_, diag| {
+            diagnostics.push(InferenceDiagnostic::PathDiagnostic { node, diag })
+        })
+    }
+
+    pub(super) fn lower_partly_resolved_path(
+        &mut self,
+        node: ExprOrPatId,
+        resolution: TypeNs,
+        resolved_segment: PathSegment<'_>,
+        remaining_segments: PathSegments<'_>,
+        resolved_segment_idx: u32,
+        infer_args: bool,
+    ) -> (Ty, Option<TypeNs>) {
+        let diagnostics = self.diagnostics;
+        self.ctx.lower_partly_resolved_path(
+            resolution,
+            resolved_segment,
+            remaining_segments,
+            resolved_segment_idx,
+            infer_args,
+            &mut |_, diag| diagnostics.push(InferenceDiagnostic::PathDiagnostic { node, diag }),
+        )
+    }
+}
+
+impl<'a> Deref for InferenceTyLoweringContext<'a> {
+    type Target = TyLoweringContext<'a>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.ctx
+    }
+}
+
+impl DerefMut for InferenceTyLoweringContext<'_> {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.ctx
+    }
+}
+
+impl Drop for InferenceTyLoweringContext<'_> {
+    fn drop(&mut self) {
+        self.diagnostics
+            .push_ty_diagnostics(self.source, std::mem::take(&mut self.ctx.diagnostics));
+    }
+}
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 a13541be695..6b6c0348dcb 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
@@ -206,7 +206,7 @@ impl InferenceContext<'_> {
                     path,
                     self.body.expr_path_hygiene(expr),
                 )
-                .map_or(true, |res| matches!(res, ValueNs::LocalBinding(_) | ValueNs::StaticId(_))),
+                .is_none_or(|res| matches!(res, ValueNs::LocalBinding(_) | ValueNs::StaticId(_))),
             Expr::Underscore => true,
             Expr::UnaryOp { op: UnaryOp::Deref, .. } => true,
             Expr::Field { .. } | Expr::Index { .. } => true,
@@ -499,7 +499,7 @@ impl InferenceContext<'_> {
                 // if the function is unresolved, we use is_varargs=true to
                 // suppress the arg count diagnostic here
                 let is_varargs =
-                    derefed_callee.callable_sig(self.db).map_or(false, |sig| sig.is_varargs)
+                    derefed_callee.callable_sig(self.db).is_some_and(|sig| sig.is_varargs)
                         || res.is_none();
                 let (param_tys, ret_ty) = match res {
                     Some((func, params, ret_ty)) => {
@@ -531,7 +531,7 @@ impl InferenceContext<'_> {
                         (params, ret_ty)
                     }
                     None => {
-                        self.result.diagnostics.push(InferenceDiagnostic::ExpectedFunction {
+                        self.push_diagnostic(InferenceDiagnostic::ExpectedFunction {
                             call_expr: tgt_expr,
                             found: callee_ty.clone(),
                         });
@@ -707,7 +707,7 @@ impl InferenceContext<'_> {
                 self.result.standard_types.never.clone()
             }
             Expr::RecordLit { path, fields, spread, .. } => {
-                let (ty, def_id) = self.resolve_variant(path.as_deref(), false);
+                let (ty, def_id) = self.resolve_variant(tgt_expr.into(), path.as_deref(), false);
 
                 if let Some(t) = expected.only_has_type(&mut self.table) {
                     self.unify(&ty, &t);
@@ -1816,9 +1816,10 @@ impl InferenceContext<'_> {
                 if !is_public {
                     if let Either::Left(field) = field_id {
                         // FIXME: Merge this diagnostic into UnresolvedField?
-                        self.result
-                            .diagnostics
-                            .push(InferenceDiagnostic::PrivateField { expr: tgt_expr, field });
+                        self.push_diagnostic(InferenceDiagnostic::PrivateField {
+                            expr: tgt_expr,
+                            field,
+                        });
                     }
                 }
                 ty
@@ -1835,7 +1836,7 @@ impl InferenceContext<'_> {
                     VisibleFromModule::Filter(self.resolver.module()),
                     name,
                 );
-                self.result.diagnostics.push(InferenceDiagnostic::UnresolvedField {
+                self.push_diagnostic(InferenceDiagnostic::UnresolvedField {
                     expr: tgt_expr,
                     receiver: receiver_ty.clone(),
                     name: name.clone(),
@@ -1927,7 +1928,7 @@ impl InferenceContext<'_> {
                     },
                 );
 
-                self.result.diagnostics.push(InferenceDiagnostic::UnresolvedMethodCall {
+                self.push_diagnostic(InferenceDiagnostic::UnresolvedMethodCall {
                     expr: tgt_expr,
                     receiver: receiver_ty.clone(),
                     name: method_name.clone(),
@@ -2042,7 +2043,7 @@ impl InferenceContext<'_> {
                     continue;
                 }
 
-                while skip_indices.peek().map_or(false, |i| *i < idx as u32) {
+                while skip_indices.peek().is_some_and(|i| *i < idx as u32) {
                     skip_indices.next();
                 }
                 if skip_indices.peek().copied() == Some(idx as u32) {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs
index 50e761196ec..00398f019da 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/pat.rs
@@ -35,7 +35,7 @@ impl InferenceContext<'_> {
         ellipsis: Option<u32>,
         subs: &[PatId],
     ) -> Ty {
-        let (ty, def) = self.resolve_variant(path, true);
+        let (ty, def) = self.resolve_variant(id.into(), path, true);
         let var_data = def.map(|it| it.variant_data(self.db.upcast()));
         if let Some(variant) = def {
             self.write_variant_resolution(id.into(), variant);
@@ -115,7 +115,7 @@ impl InferenceContext<'_> {
         id: PatId,
         subs: impl ExactSizeIterator<Item = (Name, PatId)>,
     ) -> Ty {
-        let (ty, def) = self.resolve_variant(path, false);
+        let (ty, def) = self.resolve_variant(id.into(), path, false);
         if let Some(variant) = def {
             self.write_variant_resolution(id.into(), variant);
         }
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 a6296c3af23..73bcefaf2a9 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
@@ -14,6 +14,7 @@ use crate::{
     builder::ParamKind,
     consteval, error_lifetime,
     generics::generics,
+    infer::diagnostics::InferenceTyLoweringContext as TyLoweringContext,
     method_resolution::{self, VisibleFromModule},
     to_chalk_trait_id, InferenceDiagnostic, Interner, Substitution, TraitRef, TraitRefExt, Ty,
     TyBuilder, TyExt, TyKind, ValueTyDefId,
@@ -147,36 +148,38 @@ impl InferenceContext<'_> {
         path: &Path,
         id: ExprOrPatId,
     ) -> Option<(ValueNs, Option<chalk_ir::Substitution<Interner>>)> {
+        // Don't use `self.make_ty()` here as we need `orig_ns`.
+        let mut ctx = TyLoweringContext::new(
+            self.db,
+            &self.resolver,
+            &self.body.types,
+            self.owner.into(),
+            &self.diagnostics,
+            InferenceTyDiagnosticSource::Body,
+        );
         let (value, self_subst) = if let Some(type_ref) = path.type_anchor() {
             let last = path.segments().last()?;
 
-            // Don't use `self.make_ty()` here as we need `orig_ns`.
-            let mut ctx = crate::lower::TyLoweringContext::new(
-                self.db,
-                &self.resolver,
-                &self.body.types,
-                self.owner.into(),
-            );
             let (ty, orig_ns) = ctx.lower_ty_ext(type_ref);
             let ty = self.table.insert_type_vars(ty);
             let ty = self.table.normalize_associated_types_in(ty);
 
             let remaining_segments_for_ty = path.segments().take(path.segments().len() - 1);
             let (ty, _) = ctx.lower_ty_relative_path(ty, orig_ns, remaining_segments_for_ty);
-            self.push_ty_diagnostics(InferenceTyDiagnosticSource::Body, ctx.diagnostics);
+            drop(ctx);
             let ty = self.table.insert_type_vars(ty);
             let ty = self.table.normalize_associated_types_in(ty);
             self.resolve_ty_assoc_item(ty, last.name, id).map(|(it, substs)| (it, Some(substs)))?
         } else {
             let hygiene = self.body.expr_or_pat_path_hygiene(id);
             // FIXME: report error, unresolved first path segment
-            let value_or_partial =
-                self.resolver.resolve_path_in_value_ns(self.db.upcast(), path, hygiene)?;
+            let value_or_partial = ctx.resolve_path_in_value_ns(path, id, hygiene)?;
+            drop(ctx);
 
             match value_or_partial {
                 ResolveValueResult::ValueNs(it, _) => (it, None),
                 ResolveValueResult::Partial(def, remaining_index, _) => self
-                    .resolve_assoc_item(def, path, remaining_index, id)
+                    .resolve_assoc_item(id, def, path, remaining_index, id)
                     .map(|(it, substs)| (it, Some(substs)))?,
             }
         };
@@ -212,6 +215,7 @@ impl InferenceContext<'_> {
 
     fn resolve_assoc_item(
         &mut self,
+        node: ExprOrPatId,
         def: TypeNs,
         path: &Path,
         remaining_index: usize,
@@ -260,17 +264,23 @@ impl InferenceContext<'_> {
                 // as Iterator>::Item::default`)
                 let remaining_segments_for_ty =
                     remaining_segments.take(remaining_segments.len() - 1);
-                let (ty, _) = self.with_body_ty_lowering(|ctx| {
-                    ctx.lower_partly_resolved_path(
-                        def,
-                        resolved_segment,
-                        remaining_segments_for_ty,
-                        true,
-                        &mut |_, _reason| {
-                            // FIXME: Report an error.
-                        },
-                    )
-                });
+                let mut ctx = TyLoweringContext::new(
+                    self.db,
+                    &self.resolver,
+                    &self.body.types,
+                    self.owner.into(),
+                    &self.diagnostics,
+                    InferenceTyDiagnosticSource::Body,
+                );
+                let (ty, _) = ctx.lower_partly_resolved_path(
+                    node,
+                    def,
+                    resolved_segment,
+                    remaining_segments_for_ty,
+                    (remaining_index - 1) as u32,
+                    true,
+                );
+                drop(ctx);
                 if ty.is_unknown() {
                     return None;
                 }
@@ -305,13 +315,7 @@ impl InferenceContext<'_> {
                     }
 
                     AssocItemId::ConstId(konst) => {
-                        if self
-                            .db
-                            .const_data(konst)
-                            .name
-                            .as_ref()
-                            .map_or(false, |n| n == segment.name)
-                        {
+                        if self.db.const_data(konst).name.as_ref() == Some(segment.name) {
                             Some(AssocItemId::ConstId(konst))
                         } else {
                             None
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 165861c1b17..8a8992cf372 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
@@ -282,7 +282,7 @@ impl<'a> InferenceTable<'a> {
         let is_diverging = self
             .type_variable_table
             .get(iv.index() as usize)
-            .map_or(false, |data| data.contains(TypeVariableFlags::DIVERGING));
+            .is_some_and(|data| data.contains(TypeVariableFlags::DIVERGING));
         if is_diverging {
             return TyKind::Never.intern(Interner);
         }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs b/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs
index 56b549436c7..d6039c548b6 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/inhabitedness.rs
@@ -139,7 +139,7 @@ impl UninhabitedFrom<'_> {
         ty: &Binders<Ty>,
         subst: &Substitution,
     ) -> ControlFlow<VisiblyUninhabited> {
-        if vis.map_or(true, |it| it.is_visible_from(self.db.upcast(), self.target_mod)) {
+        if vis.is_none_or(|it| it.is_visible_from(self.db.upcast(), self.target_mod)) {
             let ty = ty.clone().substitute(Interner, subst);
             ty.visit_with(self, DebruijnIndex::INNERMOST)
         } else {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lang_items.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lang_items.rs
index f704b59d303..ff9c52fbb6c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lang_items.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lang_items.rs
@@ -13,6 +13,7 @@ pub fn is_box(db: &dyn HirDatabase, adt: AdtId) -> bool {
 
 pub fn is_unsafe_cell(db: &dyn HirDatabase, adt: AdtId) -> bool {
     let AdtId::StructId(id) = adt else { return false };
+
     db.struct_data(id).flags.contains(StructFlags::IS_UNSAFE_CELL)
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs
index c1a67fcc407..0ba765bd75e 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/adt.rs
@@ -113,7 +113,7 @@ fn layout_scalar_valid_range(db: &dyn HirDatabase, def: AdtId) -> (Bound<u128>,
     let get = |name| {
         let attr = attrs.by_key(name).tt_values();
         for tree in attr {
-            if let Some(it) = tree.token_trees.first() {
+            if let Some(it) = tree.iter().next_as_view() {
                 let text = it.to_string().replace('_', "");
                 let (text, base) = match text.as_bytes() {
                     [b'0', b'x', ..] => (&text[2..], 16),
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs
index f40d508f755..66159ddce2b 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs
@@ -1,7 +1,7 @@
 use chalk_ir::{AdtId, TyKind};
 use either::Either;
 use hir_def::db::DefDatabase;
-use project_model::{target_data_layout::RustcDataLayoutConfig, Sysroot};
+use project_model::{toolchain_info::QueryConfig, Sysroot};
 use rustc_hash::FxHashMap;
 use syntax::ToSmolStr;
 use test_fixture::WithFixture;
@@ -17,8 +17,8 @@ use crate::{
 mod closure;
 
 fn current_machine_data_layout() -> String {
-    project_model::target_data_layout::get(
-        RustcDataLayoutConfig::Rustc(&Sysroot::empty()),
+    project_model::toolchain_info::target_data_layout::get(
+        QueryConfig::Rustc(&Sysroot::empty(), &std::env::current_dir().unwrap()),
         None,
         &FxHashMap::default(),
     )
@@ -241,31 +241,31 @@ fn recursive() {
 #[test]
 fn repr_packed() {
     size_and_align! {
-        #[repr(packed)]
+        #[repr(Rust, packed)]
         struct Goal;
     }
     size_and_align! {
-        #[repr(packed(2))]
+        #[repr(Rust, packed(2))]
         struct Goal;
     }
     size_and_align! {
-        #[repr(packed(4))]
+        #[repr(Rust, packed(4))]
         struct Goal;
     }
     size_and_align! {
-        #[repr(packed)]
+        #[repr(Rust, packed)]
         struct Goal(i32);
     }
     size_and_align! {
-        #[repr(packed(2))]
+        #[repr(Rust, packed(2))]
         struct Goal(i32);
     }
     size_and_align! {
-        #[repr(packed(4))]
+        #[repr(Rust, packed(4))]
         struct Goal(i32);
     }
 
-    check_size_and_align("#[repr(packed(5))] struct Goal(i32);", "", 4, 1);
+    check_size_and_align("#[repr(Rust, packed(5))] struct Goal(i32);", "", 4, 1);
 }
 
 #[test]
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 8bb90ca31e4..3c18ea92816 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
@@ -24,7 +24,6 @@ extern crate ra_ap_rustc_pattern_analysis as rustc_pattern_analysis;
 mod builder;
 mod chalk_db;
 mod chalk_ext;
-mod generics;
 mod infer;
 mod inhabitedness;
 mod interner;
@@ -39,6 +38,7 @@ pub mod db;
 pub mod diagnostics;
 pub mod display;
 pub mod dyn_compatibility;
+pub mod generics;
 pub mod lang_items;
 pub mod layout;
 pub mod method_resolution;
@@ -50,6 +50,7 @@ pub mod traits;
 mod test_db;
 #[cfg(test)]
 mod tests;
+mod variance;
 
 use std::hash::Hash;
 
@@ -89,9 +90,8 @@ pub use infer::{
 };
 pub use interner::Interner;
 pub use lower::{
-    associated_type_shorthand_candidates, GenericArgsProhibitedReason, ImplTraitLoweringMode,
-    ParamLoweringMode, TyDefId, TyLoweringContext, TyLoweringDiagnostic, TyLoweringDiagnosticKind,
-    ValueTyDefId,
+    associated_type_shorthand_candidates, diagnostics::*, ImplTraitLoweringMode, ParamLoweringMode,
+    TyDefId, TyLoweringContext, ValueTyDefId,
 };
 pub use mapping::{
     from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx,
@@ -101,6 +101,7 @@ pub use mapping::{
 pub use method_resolution::check_orphan_rules;
 pub use traits::TraitEnvironment;
 pub use utils::{all_super_traits, direct_super_traits, is_fn_unsafe_to_call};
+pub use variance::Variance;
 
 pub use chalk_ir::{
     cast::Cast,
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 b23f2749ab2..24f67fd6602 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
@@ -5,6 +5,8 @@
 //!  - Building the type for an item: This happens through the `ty` query.
 //!
 //! This usually involves resolving names, collecting generic arguments etc.
+pub(crate) mod diagnostics;
+
 use std::{
     cell::OnceCell,
     iter, mem,
@@ -21,8 +23,9 @@ use chalk_ir::{
 
 use either::Either;
 use hir_def::{
+    body::HygieneId,
     builtin_type::BuiltinType,
-    data::adt::StructKind,
+    data::{adt::StructKind, TraitFlags},
     expander::Expander,
     generics::{
         GenericParamDataRef, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
@@ -31,7 +34,7 @@ use hir_def::{
     lang_item::LangItem,
     nameres::MacroSubNs,
     path::{GenericArg, GenericArgs, ModPath, Path, PathKind, PathSegment, PathSegments},
-    resolver::{HasResolver, LifetimeNs, Resolver, TypeNs},
+    resolver::{HasResolver, LifetimeNs, ResolveValueResult, Resolver, TypeNs, ValueNs},
     type_ref::{
         ConstRef, LifetimeRef, PathId, TraitBoundModifier, TraitRef as HirTraitRef, TypeBound,
         TypeRef, TypeRefId, TypesMap, TypesSourceMap,
@@ -59,6 +62,7 @@ use crate::{
     db::HirDatabase,
     error_lifetime,
     generics::{generics, trait_self_param_idx, Generics},
+    lower::diagnostics::*,
     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,
@@ -102,31 +106,6 @@ impl ImplTraitLoweringState {
     }
 }
 
-type TypeSource = Either<TypeRefId, hir_def::type_ref::TypeSource>;
-
-#[derive(Debug, PartialEq, Eq, Clone)]
-pub struct TyLoweringDiagnostic {
-    pub source: TypeSource,
-    pub kind: TyLoweringDiagnosticKind,
-}
-
-#[derive(Debug, PartialEq, Eq, Clone)]
-pub enum TyLoweringDiagnosticKind {
-    GenericArgsProhibited { segment: u32, reason: GenericArgsProhibitedReason },
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub enum GenericArgsProhibitedReason {
-    Module,
-    TyParam,
-    SelfTy,
-    PrimitiveTy,
-    /// When there is a generic enum, within the expression `Enum::Variant`,
-    /// either `Enum` or `Variant` are allowed to have generic arguments, but not both.
-    // FIXME: This is not used now but it should be.
-    EnumVariant,
-}
-
 #[derive(Debug)]
 pub struct TyLoweringContext<'a> {
     pub db: &'a dyn HirDatabase,
@@ -536,8 +515,8 @@ impl<'a> TyLoweringContext<'a> {
     /// This is only for `generic_predicates_for_param`, where we can't just
     /// lower the self types of the predicates since that could lead to cycles.
     /// So we just check here if the `type_ref` resolves to a generic param, and which.
-    fn lower_ty_only_param(&self, type_ref: TypeRefId) -> Option<TypeOrConstParamId> {
-        let type_ref = &self.types_map[type_ref];
+    fn lower_ty_only_param(&mut self, type_ref_id: TypeRefId) -> Option<TypeOrConstParamId> {
+        let type_ref = &self.types_map[type_ref_id];
         let path = match type_ref {
             TypeRef::Path(path) => path,
             _ => return None,
@@ -548,8 +527,10 @@ impl<'a> TyLoweringContext<'a> {
         if path.segments().len() > 1 {
             return None;
         }
-        let resolution = match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path) {
-            Some((it, None, _)) => it,
+        let resolution = match self
+            .resolve_path_in_type_ns(path, &mut Self::on_path_diagnostic_callback(type_ref_id))
+        {
+            Some((it, None)) => it,
             _ => return None,
         };
         match resolution {
@@ -584,11 +565,9 @@ impl<'a> TyLoweringContext<'a> {
         resolution: TypeNs,
         resolved_segment: PathSegment<'_>,
         remaining_segments: PathSegments<'_>,
+        _resolved_segment_idx: u32,
         infer_args: bool,
-        on_prohibited_generics_for_resolved_segment: &mut dyn FnMut(
-            &mut Self,
-            GenericArgsProhibitedReason,
-        ),
+        _on_diagnostic: &mut dyn FnMut(&mut Self, PathLoweringDiagnostic),
     ) -> (Ty, Option<TypeNs>) {
         let ty = match resolution {
             TypeNs::TraitId(trait_) => {
@@ -655,44 +634,28 @@ impl<'a> TyLoweringContext<'a> {
                 // FIXME(trait_alias): Implement trait alias.
                 return (TyKind::Error.intern(Interner), None);
             }
-            TypeNs::GenericParam(param_id) => {
-                if resolved_segment.args_and_bindings.is_some() {
-                    on_prohibited_generics_for_resolved_segment(
-                        self,
-                        GenericArgsProhibitedReason::TyParam,
-                    );
+            TypeNs::GenericParam(param_id) => match self.type_param_mode {
+                ParamLoweringMode::Placeholder => {
+                    TyKind::Placeholder(to_placeholder_idx(self.db, param_id.into()))
                 }
+                ParamLoweringMode::Variable => {
+                    let idx = match self
+                        .generics()
+                        .expect("generics in scope")
+                        .type_or_const_param_idx(param_id.into())
+                    {
+                        None => {
+                            never!("no matching generics");
+                            return (TyKind::Error.intern(Interner), None);
+                        }
+                        Some(idx) => idx,
+                    };
 
-                match self.type_param_mode {
-                    ParamLoweringMode::Placeholder => {
-                        TyKind::Placeholder(to_placeholder_idx(self.db, param_id.into()))
-                    }
-                    ParamLoweringMode::Variable => {
-                        let idx = match self
-                            .generics()
-                            .expect("generics in scope")
-                            .type_or_const_param_idx(param_id.into())
-                        {
-                            None => {
-                                never!("no matching generics");
-                                return (TyKind::Error.intern(Interner), None);
-                            }
-                            Some(idx) => idx,
-                        };
-
-                        TyKind::BoundVar(BoundVar::new(self.in_binders, idx))
-                    }
+                    TyKind::BoundVar(BoundVar::new(self.in_binders, idx))
                 }
-                .intern(Interner)
             }
+            .intern(Interner),
             TypeNs::SelfType(impl_id) => {
-                if resolved_segment.args_and_bindings.is_some() {
-                    on_prohibited_generics_for_resolved_segment(
-                        self,
-                        GenericArgsProhibitedReason::SelfTy,
-                    );
-                }
-
                 let generics = self.generics().expect("impl should have generic param scope");
 
                 match self.type_param_mode {
@@ -718,13 +681,6 @@ impl<'a> TyLoweringContext<'a> {
                 }
             }
             TypeNs::AdtSelfType(adt) => {
-                if resolved_segment.args_and_bindings.is_some() {
-                    on_prohibited_generics_for_resolved_segment(
-                        self,
-                        GenericArgsProhibitedReason::SelfTy,
-                    );
-                }
-
                 let generics = generics(self.db.upcast(), adt.into());
                 let substs = match self.type_param_mode {
                     ParamLoweringMode::Placeholder => generics.placeholder_subst(self.db),
@@ -737,12 +693,6 @@ impl<'a> TyLoweringContext<'a> {
 
             TypeNs::AdtId(it) => self.lower_path_inner(resolved_segment, it.into(), infer_args),
             TypeNs::BuiltinType(it) => {
-                if resolved_segment.args_and_bindings.is_some() {
-                    on_prohibited_generics_for_resolved_segment(
-                        self,
-                        GenericArgsProhibitedReason::PrimitiveTy,
-                    );
-                }
                 self.lower_path_inner(resolved_segment, it.into(), infer_args)
             }
             TypeNs::TypeAliasId(it) => {
@@ -754,6 +704,220 @@ impl<'a> TyLoweringContext<'a> {
         self.lower_ty_relative_path(ty, Some(resolution), remaining_segments)
     }
 
+    fn handle_type_ns_resolution(
+        &mut self,
+        resolution: &TypeNs,
+        resolved_segment: PathSegment<'_>,
+        resolved_segment_idx: usize,
+        on_diagnostic: &mut dyn FnMut(&mut Self, PathLoweringDiagnostic),
+    ) {
+        let mut prohibit_generics_on_resolved = |reason| {
+            if resolved_segment.args_and_bindings.is_some() {
+                on_diagnostic(
+                    self,
+                    PathLoweringDiagnostic::GenericArgsProhibited {
+                        segment: resolved_segment_idx as u32,
+                        reason,
+                    },
+                );
+            }
+        };
+
+        match resolution {
+            TypeNs::SelfType(_) => {
+                prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy)
+            }
+            TypeNs::GenericParam(_) => {
+                prohibit_generics_on_resolved(GenericArgsProhibitedReason::TyParam)
+            }
+            TypeNs::AdtSelfType(_) => {
+                prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy)
+            }
+            TypeNs::BuiltinType(_) => {
+                prohibit_generics_on_resolved(GenericArgsProhibitedReason::PrimitiveTy)
+            }
+            TypeNs::AdtId(_)
+            | TypeNs::EnumVariantId(_)
+            | TypeNs::TypeAliasId(_)
+            | TypeNs::TraitId(_)
+            | TypeNs::TraitAliasId(_) => {}
+        }
+    }
+
+    pub(crate) fn resolve_path_in_type_ns_fully(
+        &mut self,
+        path: &Path,
+        on_diagnostic: &mut dyn FnMut(&mut Self, PathLoweringDiagnostic),
+    ) -> Option<TypeNs> {
+        let (res, unresolved) = self.resolve_path_in_type_ns(path, on_diagnostic)?;
+        if unresolved.is_some() {
+            return None;
+        }
+        Some(res)
+    }
+
+    pub(crate) fn resolve_path_in_type_ns(
+        &mut self,
+        path: &Path,
+        on_diagnostic: &mut dyn FnMut(&mut Self, PathLoweringDiagnostic),
+    ) -> Option<(TypeNs, Option<usize>)> {
+        let (resolution, remaining_index, _) =
+            self.resolver.resolve_path_in_type_ns(self.db.upcast(), path)?;
+        let segments = path.segments();
+
+        match path {
+            // `segments.is_empty()` can occur with `self`.
+            Path::Normal(..) if !segments.is_empty() => (),
+            _ => return Some((resolution, remaining_index)),
+        };
+
+        let (module_segments, resolved_segment_idx, resolved_segment) = match remaining_index {
+            None => (
+                segments.strip_last(),
+                segments.len() - 1,
+                segments.last().expect("resolved path has at least one element"),
+            ),
+            Some(i) => (segments.take(i - 1), i - 1, segments.get(i - 1).unwrap()),
+        };
+
+        for (i, mod_segment) in module_segments.iter().enumerate() {
+            if mod_segment.args_and_bindings.is_some() {
+                on_diagnostic(
+                    self,
+                    PathLoweringDiagnostic::GenericArgsProhibited {
+                        segment: i as u32,
+                        reason: GenericArgsProhibitedReason::Module,
+                    },
+                );
+            }
+        }
+
+        self.handle_type_ns_resolution(
+            &resolution,
+            resolved_segment,
+            resolved_segment_idx,
+            on_diagnostic,
+        );
+
+        Some((resolution, remaining_index))
+    }
+
+    pub(crate) fn resolve_path_in_value_ns(
+        &mut self,
+        path: &Path,
+        hygiene_id: HygieneId,
+        on_diagnostic: &mut dyn FnMut(&mut Self, PathLoweringDiagnostic),
+    ) -> Option<ResolveValueResult> {
+        let (res, prefix_info) = self.resolver.resolve_path_in_value_ns_with_prefix_info(
+            self.db.upcast(),
+            path,
+            hygiene_id,
+        )?;
+
+        let segments = path.segments();
+        match path {
+            // `segments.is_empty()` can occur with `self`.
+            Path::Normal(..) if !segments.is_empty() => (),
+            _ => return Some(res),
+        };
+
+        let (mod_segments, enum_segment) = match res {
+            ResolveValueResult::Partial(_, unresolved_segment, _) => {
+                (segments.take(unresolved_segment - 1), None)
+            }
+            ResolveValueResult::ValueNs(ValueNs::EnumVariantId(_), _)
+                if prefix_info.enum_variant =>
+            {
+                (segments.strip_last_two(), segments.len().checked_sub(2))
+            }
+            ResolveValueResult::ValueNs(..) => (segments.strip_last(), None),
+        };
+        for (i, mod_segment) in mod_segments.iter().enumerate() {
+            if mod_segment.args_and_bindings.is_some() {
+                on_diagnostic(
+                    self,
+                    PathLoweringDiagnostic::GenericArgsProhibited {
+                        segment: i as u32,
+                        reason: GenericArgsProhibitedReason::Module,
+                    },
+                );
+            }
+        }
+
+        if let Some(enum_segment) = enum_segment {
+            if segments.get(enum_segment).is_some_and(|it| it.args_and_bindings.is_some())
+                && segments.get(enum_segment + 1).is_some_and(|it| it.args_and_bindings.is_some())
+            {
+                on_diagnostic(
+                    self,
+                    PathLoweringDiagnostic::GenericArgsProhibited {
+                        segment: (enum_segment + 1) as u32,
+                        reason: GenericArgsProhibitedReason::EnumVariant,
+                    },
+                );
+            }
+        }
+
+        match &res {
+            ResolveValueResult::ValueNs(resolution, _) => {
+                let resolved_segment_idx =
+                    segments.len().checked_sub(1).unwrap_or_else(|| panic!("{path:?}"));
+                let resolved_segment = segments.last().unwrap();
+
+                let mut prohibit_generics_on_resolved = |reason| {
+                    if resolved_segment.args_and_bindings.is_some() {
+                        on_diagnostic(
+                            self,
+                            PathLoweringDiagnostic::GenericArgsProhibited {
+                                segment: resolved_segment_idx as u32,
+                                reason,
+                            },
+                        );
+                    }
+                };
+
+                match resolution {
+                    ValueNs::ImplSelf(_) => {
+                        prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy)
+                    }
+                    // FIXME: rustc generates E0107 (incorrect number of generic arguments) and not
+                    // E0109 (generic arguments provided for a type that doesn't accept them) for
+                    // consts and statics, presumably as a defense against future in which consts
+                    // and statics can be generic, or just because it was easier for rustc implementors.
+                    // That means we'll show the wrong error code. Because of us it's easier to do it
+                    // this way :)
+                    ValueNs::GenericParam(_) | ValueNs::ConstId(_) => {
+                        prohibit_generics_on_resolved(GenericArgsProhibitedReason::Const)
+                    }
+                    ValueNs::StaticId(_) => {
+                        prohibit_generics_on_resolved(GenericArgsProhibitedReason::Static)
+                    }
+                    ValueNs::FunctionId(_) | ValueNs::StructId(_) | ValueNs::EnumVariantId(_) => {}
+                    ValueNs::LocalBinding(_) => {}
+                }
+            }
+            ResolveValueResult::Partial(resolution, unresolved_idx, _) => {
+                let resolved_segment_idx = unresolved_idx - 1;
+                let resolved_segment = segments.get(resolved_segment_idx).unwrap();
+                self.handle_type_ns_resolution(
+                    resolution,
+                    resolved_segment,
+                    resolved_segment_idx,
+                    on_diagnostic,
+                );
+            }
+        };
+        Some(res)
+    }
+
+    fn on_path_diagnostic_callback(
+        type_ref: TypeRefId,
+    ) -> impl FnMut(&mut Self, PathLoweringDiagnostic) {
+        move |this, diag| {
+            this.push_diagnostic(type_ref, TyLoweringDiagnosticKind::PathDiagnostic(diag))
+        }
+    }
+
     pub(crate) fn lower_path(&mut self, path: &Path, path_id: PathId) -> (Ty, Option<TypeNs>) {
         // Resolve the path (in type namespace)
         if let Some(type_ref) = path.type_anchor() {
@@ -761,11 +925,13 @@ impl<'a> TyLoweringContext<'a> {
             return self.lower_ty_relative_path(ty, res, path.segments());
         }
 
-        let (resolution, remaining_index, _) =
-            match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path) {
-                Some(it) => it,
-                None => return (TyKind::Error.intern(Interner), None),
-            };
+        let (resolution, remaining_index) = match self.resolve_path_in_type_ns(
+            path,
+            &mut Self::on_path_diagnostic_callback(path_id.type_ref()),
+        ) {
+            Some(it) => it,
+            None => return (TyKind::Error.intern(Interner), None),
+        };
 
         if matches!(resolution, TypeNs::TraitId(_)) && remaining_index.is_none() {
             // trait object type without dyn
@@ -774,38 +940,22 @@ impl<'a> TyLoweringContext<'a> {
             return (ty, None);
         }
 
-        let (module_segments, resolved_segment_idx, resolved_segment, remaining_segments) =
-            match remaining_index {
-                None => (
-                    path.segments().strip_last(),
-                    path.segments().len() - 1,
-                    path.segments().last().expect("resolved path has at least one element"),
-                    PathSegments::EMPTY,
-                ),
-                Some(i) => (
-                    path.segments().take(i - 1),
-                    i - 1,
-                    path.segments().get(i - 1).unwrap(),
-                    path.segments().skip(i),
-                ),
-            };
-
-        self.prohibit_generics(path_id, 0, module_segments, GenericArgsProhibitedReason::Module);
+        let (resolved_segment_idx, resolved_segment, remaining_segments) = match remaining_index {
+            None => (
+                path.segments().len() - 1,
+                path.segments().last().expect("resolved path has at least one element"),
+                PathSegments::EMPTY,
+            ),
+            Some(i) => (i - 1, path.segments().get(i - 1).unwrap(), path.segments().skip(i)),
+        };
 
         self.lower_partly_resolved_path(
             resolution,
             resolved_segment,
             remaining_segments,
+            resolved_segment_idx as u32,
             false,
-            &mut |this, reason| {
-                this.push_diagnostic(
-                    path_id.type_ref(),
-                    TyLoweringDiagnosticKind::GenericArgsProhibited {
-                        segment: resolved_segment_idx as u32,
-                        reason,
-                    },
-                )
-            },
+            &mut Self::on_path_diagnostic_callback(path_id.type_ref()),
         )
     }
 
@@ -1107,7 +1257,9 @@ impl<'a> TyLoweringContext<'a> {
             if segment.args_and_bindings.is_some() {
                 self.push_diagnostic(
                     path_id.type_ref(),
-                    TyLoweringDiagnosticKind::GenericArgsProhibited { segment: idx, reason },
+                    TyLoweringDiagnosticKind::PathDiagnostic(
+                        PathLoweringDiagnostic::GenericArgsProhibited { segment: idx, reason },
+                    ),
                 );
             }
         });
@@ -1119,7 +1271,10 @@ impl<'a> TyLoweringContext<'a> {
         explicit_self_ty: Ty,
     ) -> Option<TraitRef> {
         let path = &self.types_map[path_id];
-        let resolved = match self.resolver.resolve_path_in_type_ns_fully(self.db.upcast(), path)? {
+        let resolved = match self.resolve_path_in_type_ns_fully(
+            path,
+            &mut Self::on_path_diagnostic_callback(path_id.type_ref()),
+        )? {
             // FIXME(trait_alias): We need to handle trait alias here.
             TypeNs::TraitId(tr) => tr,
             _ => return None,
@@ -1412,9 +1567,17 @@ impl<'a> TyLoweringContext<'a> {
                 match (lhs.skip_binders(), rhs.skip_binders()) {
                     (WhereClause::Implemented(lhs), WhereClause::Implemented(rhs)) => {
                         let lhs_id = lhs.trait_id;
-                        let lhs_is_auto = ctx.db.trait_data(from_chalk_trait_id(lhs_id)).is_auto;
+                        let lhs_is_auto = ctx
+                            .db
+                            .trait_data(from_chalk_trait_id(lhs_id))
+                            .flags
+                            .contains(TraitFlags::IS_AUTO);
                         let rhs_id = rhs.trait_id;
-                        let rhs_is_auto = ctx.db.trait_data(from_chalk_trait_id(rhs_id)).is_auto;
+                        let rhs_is_auto = ctx
+                            .db
+                            .trait_data(from_chalk_trait_id(rhs_id))
+                            .flags
+                            .contains(TraitFlags::IS_AUTO);
 
                         if !lhs_is_auto && !rhs_is_auto {
                             multiple_regular_traits = true;
@@ -2588,14 +2751,14 @@ fn fallback_bound_vars<T: TypeFoldable<Interner> + HasInterner<Interner = Intern
     crate::fold_free_vars(
         s,
         |bound, binders| {
-            if bound.index_if_innermost().map_or(true, is_allowed) {
+            if bound.index_if_innermost().is_none_or(is_allowed) {
                 bound.shifted_in_from(binders).to_ty(Interner)
             } else {
                 TyKind::Error.intern(Interner)
             }
         },
         |ty, bound, binders| {
-            if bound.index_if_innermost().map_or(true, is_allowed) {
+            if bound.index_if_innermost().is_none_or(is_allowed) {
                 bound.shifted_in_from(binders).to_const(Interner, ty)
             } else {
                 unknown_const(ty)
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower/diagnostics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower/diagnostics.rs
new file mode 100644
index 00000000000..7fe196cdbb5
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower/diagnostics.rs
@@ -0,0 +1,36 @@
+//! This files contains the declaration of diagnostics kinds for ty and path lowering.
+
+use either::Either;
+use hir_def::type_ref::TypeRefId;
+
+type TypeSource = Either<TypeRefId, hir_def::type_ref::TypeSource>;
+
+#[derive(Debug, PartialEq, Eq, Clone)]
+pub struct TyLoweringDiagnostic {
+    pub source: TypeSource,
+    pub kind: TyLoweringDiagnosticKind,
+}
+
+#[derive(Debug, PartialEq, Eq, Clone)]
+pub enum TyLoweringDiagnosticKind {
+    PathDiagnostic(PathLoweringDiagnostic),
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum GenericArgsProhibitedReason {
+    Module,
+    TyParam,
+    SelfTy,
+    PrimitiveTy,
+    Const,
+    Static,
+    /// When there is a generic enum, within the expression `Enum::Variant`,
+    /// either `Enum` or `Variant` are allowed to have generic arguments, but not both.
+    // FIXME: This is not used now but it should be.
+    EnumVariant,
+}
+
+#[derive(Debug, PartialEq, Eq, Clone)]
+pub enum PathLoweringDiagnostic {
+    GenericArgsProhibited { segment: u32, reason: GenericArgsProhibitedReason },
+}
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 5a72b97653d..62b071b2f32 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
@@ -7,7 +7,7 @@ use std::ops::ControlFlow;
 use base_db::CrateId;
 use chalk_ir::{cast::Cast, UniverseIndex, WithKind};
 use hir_def::{
-    data::{adt::StructFlags, ImplData},
+    data::{adt::StructFlags, ImplData, TraitFlags},
     nameres::DefMap,
     AssocItemId, BlockId, ConstId, FunctionId, HasModule, ImplId, ItemContainerId, Lookup,
     ModuleId, TraitId,
@@ -377,7 +377,7 @@ pub(crate) fn incoherent_inherent_impl_crates(
 
     for krate in crate_graph.transitive_deps(krate) {
         let impls = db.inherent_impls_in_crate(krate);
-        if impls.map.get(&fp).map_or(false, |v| !v.is_empty()) {
+        if impls.map.get(&fp).is_some_and(|v| !v.is_empty()) {
             res.push(krate);
         }
     }
@@ -419,11 +419,17 @@ pub fn def_crates(
         }
         TyKind::Dyn(_) => {
             let trait_id = ty.dyn_trait()?;
-            Some(if db.trait_data(trait_id).rustc_has_incoherent_inherent_impls {
-                db.incoherent_inherent_impl_crates(cur_crate, TyFingerprint::Dyn(trait_id))
-            } else {
-                smallvec![trait_id.module(db.upcast()).krate()]
-            })
+            Some(
+                if db
+                    .trait_data(trait_id)
+                    .flags
+                    .contains(TraitFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS)
+                {
+                    db.incoherent_inherent_impl_crates(cur_crate, TyFingerprint::Dyn(trait_id))
+                } else {
+                    smallvec![trait_id.module(db.upcast()).krate()]
+                },
+            )
         }
         // for primitives, there may be impls in various places (core and alloc
         // mostly). We just check the whole crate graph for crates with impls
@@ -805,8 +811,8 @@ fn is_inherent_impl_coherent(
         | TyKind::Scalar(_) => def_map.is_rustc_coherence_is_core(),
 
         &TyKind::Adt(AdtId(adt), _) => adt.module(db.upcast()).krate() == def_map.krate(),
-        TyKind::Dyn(it) => it.principal().map_or(false, |trait_ref| {
-            from_chalk_trait_id(trait_ref.trait_id).module(db.upcast()).krate() == def_map.krate()
+        TyKind::Dyn(it) => it.principal_id().is_some_and(|trait_id| {
+            from_chalk_trait_id(trait_id).module(db.upcast()).krate() == def_map.krate()
         }),
 
         _ => true,
@@ -834,9 +840,10 @@ fn is_inherent_impl_coherent(
                     .contains(StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL),
                 hir_def::AdtId::EnumId(it) => db.enum_data(it).rustc_has_incoherent_inherent_impls,
             },
-            TyKind::Dyn(it) => it.principal().map_or(false, |trait_ref| {
-                db.trait_data(from_chalk_trait_id(trait_ref.trait_id))
-                    .rustc_has_incoherent_inherent_impls
+            TyKind::Dyn(it) => it.principal_id().is_some_and(|trait_id| {
+                db.trait_data(from_chalk_trait_id(trait_id))
+                    .flags
+                    .contains(TraitFlags::RUSTC_HAS_INCOHERENT_INHERENT_IMPLS)
             }),
 
             _ => false,
@@ -896,8 +903,8 @@ pub fn check_orphan_rules(db: &dyn HirDatabase, impl_: ImplId) -> bool {
         match unwrap_fundamental(ty).kind(Interner) {
             &TyKind::Adt(AdtId(id), _) => is_local(id.module(db.upcast()).krate()),
             TyKind::Error => true,
-            TyKind::Dyn(it) => it.principal().map_or(false, |trait_ref| {
-                is_local(from_chalk_trait_id(trait_ref.trait_id).module(db.upcast()).krate())
+            TyKind::Dyn(it) => it.principal_id().is_some_and(|trait_id| {
+                is_local(from_chalk_trait_id(trait_id).module(db.upcast()).krate())
             }),
             _ => false,
         }
@@ -914,7 +921,7 @@ pub fn iterate_path_candidates(
     traits_in_scope: &FxHashSet<TraitId>,
     visible_from_module: VisibleFromModule,
     name: Option<&Name>,
-    callback: &mut dyn FnMut(AssocItemId) -> ControlFlow<()>,
+    callback: &mut dyn MethodCandidateCallback,
 ) -> ControlFlow<()> {
     iterate_method_candidates_dyn(
         ty,
@@ -925,7 +932,7 @@ pub fn iterate_path_candidates(
         name,
         LookupMode::Path,
         // the adjustments are not relevant for path lookup
-        &mut |_, id, _| callback(id),
+        callback,
     )
 }
 
@@ -937,7 +944,7 @@ pub fn iterate_method_candidates_dyn(
     visible_from_module: VisibleFromModule,
     name: Option<&Name>,
     mode: LookupMode,
-    callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
+    callback: &mut dyn MethodCandidateCallback,
 ) -> ControlFlow<()> {
     let _p = tracing::info_span!(
         "iterate_method_candidates_dyn",
@@ -1007,7 +1014,7 @@ fn iterate_method_candidates_with_autoref(
     traits_in_scope: &FxHashSet<TraitId>,
     visible_from_module: VisibleFromModule,
     name: Option<&Name>,
-    mut callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
+    callback: &mut dyn MethodCandidateCallback,
 ) -> ControlFlow<()> {
     if receiver_ty.value.is_general_var(Interner, &receiver_ty.binders) {
         // don't try to resolve methods on unknown types
@@ -1022,7 +1029,7 @@ fn iterate_method_candidates_with_autoref(
             traits_in_scope,
             visible_from_module,
             name,
-            &mut callback,
+            callback,
         )
     };
 
@@ -1052,6 +1059,45 @@ fn iterate_method_candidates_with_autoref(
     iterate_method_candidates_by_receiver(ref_muted, first_adjustment.with_autoref(Mutability::Mut))
 }
 
+pub trait MethodCandidateCallback {
+    fn on_inherent_method(
+        &mut self,
+        adjustments: ReceiverAdjustments,
+        item: AssocItemId,
+        is_visible: bool,
+    ) -> ControlFlow<()>;
+
+    fn on_trait_method(
+        &mut self,
+        adjustments: ReceiverAdjustments,
+        item: AssocItemId,
+        is_visible: bool,
+    ) -> ControlFlow<()>;
+}
+
+impl<F> MethodCandidateCallback for F
+where
+    F: FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
+{
+    fn on_inherent_method(
+        &mut self,
+        adjustments: ReceiverAdjustments,
+        item: AssocItemId,
+        is_visible: bool,
+    ) -> ControlFlow<()> {
+        self(adjustments, item, is_visible)
+    }
+
+    fn on_trait_method(
+        &mut self,
+        adjustments: ReceiverAdjustments,
+        item: AssocItemId,
+        is_visible: bool,
+    ) -> ControlFlow<()> {
+        self(adjustments, item, is_visible)
+    }
+}
+
 #[tracing::instrument(skip_all, fields(name = ?name))]
 fn iterate_method_candidates_by_receiver(
     table: &mut InferenceTable<'_>,
@@ -1060,7 +1106,7 @@ fn iterate_method_candidates_by_receiver(
     traits_in_scope: &FxHashSet<TraitId>,
     visible_from_module: VisibleFromModule,
     name: Option<&Name>,
-    mut callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
+    callback: &mut dyn MethodCandidateCallback,
 ) -> ControlFlow<()> {
     let receiver_ty = table.instantiate_canonical(receiver_ty);
     // We're looking for methods with *receiver* type receiver_ty. These could
@@ -1076,7 +1122,9 @@ fn iterate_method_candidates_by_receiver(
                 Some(&receiver_ty),
                 Some(receiver_adjustments.clone()),
                 visible_from_module,
-                &mut callback,
+                &mut |adjustments, item, is_visible| {
+                    callback.on_inherent_method(adjustments, item, is_visible)
+                },
             )?
         }
         ControlFlow::Continue(())
@@ -1096,7 +1144,9 @@ fn iterate_method_candidates_by_receiver(
                 name,
                 Some(&receiver_ty),
                 Some(receiver_adjustments.clone()),
-                &mut callback,
+                &mut |adjustments, item, is_visible| {
+                    callback.on_trait_method(adjustments, item, is_visible)
+                },
             )?
         }
         ControlFlow::Continue(())
@@ -1111,7 +1161,7 @@ fn iterate_method_candidates_for_self_ty(
     traits_in_scope: &FxHashSet<TraitId>,
     visible_from_module: VisibleFromModule,
     name: Option<&Name>,
-    mut callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
+    callback: &mut dyn MethodCandidateCallback,
 ) -> ControlFlow<()> {
     let mut table = InferenceTable::new(db, env);
     let self_ty = table.instantiate_canonical(self_ty.clone());
@@ -1122,7 +1172,9 @@ fn iterate_method_candidates_for_self_ty(
         None,
         None,
         visible_from_module,
-        &mut callback,
+        &mut |adjustments, item, is_visible| {
+            callback.on_inherent_method(adjustments, item, is_visible)
+        },
     )?;
     iterate_trait_method_candidates(
         &self_ty,
@@ -1131,7 +1183,9 @@ fn iterate_method_candidates_for_self_ty(
         name,
         None,
         None,
-        callback,
+        &mut |adjustments, item, is_visible| {
+            callback.on_trait_method(adjustments, item, is_visible)
+        },
     )
 }
 
@@ -1158,7 +1212,7 @@ fn iterate_trait_method_candidates(
         // 2021.
         // This is to make `[a].into_iter()` not break code with the new `IntoIterator` impl for
         // arrays.
-        if data.skip_array_during_method_dispatch
+        if data.flags.contains(TraitFlags::SKIP_ARRAY_DURING_METHOD_DISPATCH)
             && matches!(self_ty.kind(Interner), TyKind::Array(..))
         {
             // FIXME: this should really be using the edition of the method name's span, in case it
@@ -1167,7 +1221,7 @@ fn iterate_trait_method_candidates(
                 continue;
             }
         }
-        if data.skip_boxed_slice_during_method_dispatch
+        if data.flags.contains(TraitFlags::SKIP_BOXED_SLICE_DURING_METHOD_DISPATCH)
             && matches!(
                 self_ty.kind(Interner), TyKind::Adt(AdtId(def), subst)
                 if is_box(table.db, *def)
@@ -1427,7 +1481,7 @@ fn is_valid_impl_method_candidate(
         AssocItemId::ConstId(c) => {
             let db = table.db;
             check_that!(receiver_ty.is_none());
-            check_that!(name.map_or(true, |n| db.const_data(c).name.as_ref() == Some(n)));
+            check_that!(name.is_none_or(|n| db.const_data(c).name.as_ref() == Some(n)));
 
             if let Some(from_module) = visible_from_module {
                 if !db.const_visibility(c).is_visible_from(db.upcast(), from_module) {
@@ -1465,7 +1519,7 @@ fn is_valid_trait_method_candidate(
         AssocItemId::FunctionId(fn_id) => {
             let data = db.function_data(fn_id);
 
-            check_that!(name.map_or(true, |n| n == &data.name));
+            check_that!(name.is_none_or(|n| n == &data.name));
 
             table.run_in_snapshot(|table| {
                 let impl_subst = TyBuilder::subst_for_def(db, trait_id, None)
@@ -1494,7 +1548,7 @@ fn is_valid_trait_method_candidate(
         }
         AssocItemId::ConstId(c) => {
             check_that!(receiver_ty.is_none());
-            check_that!(name.map_or(true, |n| db.const_data(c).name.as_ref() == Some(n)));
+            check_that!(name.is_none_or(|n| db.const_data(c).name.as_ref() == Some(n)));
 
             IsValidCandidate::Yes
         }
@@ -1515,7 +1569,7 @@ fn is_valid_impl_fn_candidate(
     let db = table.db;
     let data = db.function_data(fn_id);
 
-    check_that!(name.map_or(true, |n| n == &data.name));
+    check_that!(name.is_none_or(|n| n == &data.name));
     if let Some(from_module) = visible_from_module {
         if !db.function_visibility(fn_id).is_visible_from(db.upcast(), from_module) {
             cov_mark::hit!(autoderef_candidate_not_visible);
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 e3072d6ee79..dcae6877ba8 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
@@ -1211,7 +1211,9 @@ impl Evaluator<'_> {
                         }
                         lc = &lc[..self.ptr_size()];
                         rc = &rc[..self.ptr_size()];
-                        ls
+                        lc = self.read_memory(Address::from_bytes(lc)?, ls)?;
+                        rc = self.read_memory(Address::from_bytes(rc)?, ls)?;
+                        break 'binary_op Owned(vec![u8::from(lc == rc)]);
                     } else {
                         self.size_of_sized(&ty, locals, "operand of binary op")?
                     };
@@ -1340,18 +1342,8 @@ impl Evaluator<'_> {
                     }
                 } else {
                     let is_signed = matches!(ty.as_builtin(), Some(BuiltinType::Int(_)));
-                    let l128 = i128::from_le_bytes(pad16(lc, is_signed));
-                    let r128 = i128::from_le_bytes(pad16(rc, is_signed));
-                    let check_overflow = |r: i128| {
-                        // FIXME: this is not very correct, and only catches the basic cases.
-                        let r = r.to_le_bytes();
-                        for &k in &r[lc.len()..] {
-                            if k != 0 && (k != 255 || !is_signed) {
-                                return Err(MirEvalError::Panic(format!("Overflow in {op:?}")));
-                            }
-                        }
-                        Ok(Owned(r[0..lc.len()].into()))
-                    };
+                    let l128 = IntValue::from_bytes(lc, is_signed);
+                    let r128 = IntValue::from_bytes(rc, is_signed);
                     match op {
                         BinOp::Ge | BinOp::Gt | BinOp::Le | BinOp::Lt | BinOp::Eq | BinOp::Ne => {
                             let r = op.run_compare(l128, r128) as u8;
@@ -1366,25 +1358,31 @@ impl Evaluator<'_> {
                         | BinOp::Rem
                         | BinOp::Sub => {
                             let r = match op {
-                                BinOp::Add => l128.overflowing_add(r128).0,
-                                BinOp::Mul => l128.overflowing_mul(r128).0,
+                                BinOp::Add => l128.checked_add(r128).ok_or_else(|| {
+                                    MirEvalError::Panic(format!("Overflow in {op:?}"))
+                                })?,
+                                BinOp::Mul => l128.checked_mul(r128).ok_or_else(|| {
+                                    MirEvalError::Panic(format!("Overflow in {op:?}"))
+                                })?,
                                 BinOp::Div => l128.checked_div(r128).ok_or_else(|| {
                                     MirEvalError::Panic(format!("Overflow in {op:?}"))
                                 })?,
                                 BinOp::Rem => l128.checked_rem(r128).ok_or_else(|| {
                                     MirEvalError::Panic(format!("Overflow in {op:?}"))
                                 })?,
-                                BinOp::Sub => l128.overflowing_sub(r128).0,
+                                BinOp::Sub => l128.checked_sub(r128).ok_or_else(|| {
+                                    MirEvalError::Panic(format!("Overflow in {op:?}"))
+                                })?,
                                 BinOp::BitAnd => l128 & r128,
                                 BinOp::BitOr => l128 | r128,
                                 BinOp::BitXor => l128 ^ r128,
                                 _ => unreachable!(),
                             };
-                            check_overflow(r)?
+                            Owned(r.to_bytes())
                         }
                         BinOp::Shl | BinOp::Shr => {
                             let r = 'b: {
-                                if let Ok(shift_amount) = u32::try_from(r128) {
+                                if let Some(shift_amount) = r128.as_u32() {
                                     let r = match op {
                                         BinOp::Shl => l128.checked_shl(shift_amount),
                                         BinOp::Shr => l128.checked_shr(shift_amount),
@@ -1401,7 +1399,7 @@ impl Evaluator<'_> {
                                 };
                                 return Err(MirEvalError::Panic(format!("Overflow in {op:?}")));
                             };
-                            Owned(r.to_le_bytes()[..lc.len()].to_vec())
+                            Owned(r.to_bytes())
                         }
                         BinOp::Offset => not_supported!("offset binop"),
                     }
@@ -2115,7 +2113,7 @@ impl Evaluator<'_> {
         while self.heap.len() % align != 0 {
             self.heap.push(0);
         }
-        if size.checked_add(self.heap.len()).map_or(true, |x| x > self.memory_limit) {
+        if size.checked_add(self.heap.len()).is_none_or(|x| x > self.memory_limit) {
             return Err(MirEvalError::Panic(format!("Memory allocation of {size} bytes failed")));
         }
         let pos = self.heap.len();
@@ -2974,3 +2972,129 @@ pub fn pad16(it: &[u8], is_signed: bool) -> [u8; 16] {
     res[..it.len()].copy_from_slice(it);
     res
 }
+
+macro_rules! for_each_int_type {
+    ($call_macro:path, $args:tt) => {
+        $call_macro! {
+            $args
+            I8
+            U8
+            I16
+            U16
+            I32
+            U32
+            I64
+            U64
+            I128
+            U128
+        }
+    };
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+enum IntValue {
+    I8(i8),
+    U8(u8),
+    I16(i16),
+    U16(u16),
+    I32(i32),
+    U32(u32),
+    I64(i64),
+    U64(u64),
+    I128(i128),
+    U128(u128),
+}
+
+macro_rules! checked_int_op {
+    ( [ $op:ident ] $( $int_ty:ident )+ ) => {
+        fn $op(self, other: Self) -> Option<Self> {
+            match (self, other) {
+                $( (Self::$int_ty(a), Self::$int_ty(b)) => a.$op(b).map(Self::$int_ty), )+
+                _ => panic!("incompatible integer types"),
+            }
+        }
+    };
+}
+
+macro_rules! int_bit_shifts {
+    ( [ $op:ident ] $( $int_ty:ident )+ ) => {
+        fn $op(self, amount: u32) -> Option<Self> {
+            match self {
+                $( Self::$int_ty(this) => this.$op(amount).map(Self::$int_ty), )+
+            }
+        }
+    };
+}
+
+macro_rules! unchecked_int_op {
+    ( [ $name:ident, $op:tt ]  $( $int_ty:ident )+ ) => {
+        fn $name(self, other: Self) -> Self {
+            match (self, other) {
+                $( (Self::$int_ty(a), Self::$int_ty(b)) => Self::$int_ty(a $op b), )+
+                _ => panic!("incompatible integer types"),
+            }
+        }
+    };
+}
+
+impl IntValue {
+    fn from_bytes(bytes: &[u8], is_signed: bool) -> Self {
+        match (bytes.len(), is_signed) {
+            (1, false) => Self::U8(u8::from_le_bytes(bytes.try_into().unwrap())),
+            (1, true) => Self::I8(i8::from_le_bytes(bytes.try_into().unwrap())),
+            (2, false) => Self::U16(u16::from_le_bytes(bytes.try_into().unwrap())),
+            (2, true) => Self::I16(i16::from_le_bytes(bytes.try_into().unwrap())),
+            (4, false) => Self::U32(u32::from_le_bytes(bytes.try_into().unwrap())),
+            (4, true) => Self::I32(i32::from_le_bytes(bytes.try_into().unwrap())),
+            (8, false) => Self::U64(u64::from_le_bytes(bytes.try_into().unwrap())),
+            (8, true) => Self::I64(i64::from_le_bytes(bytes.try_into().unwrap())),
+            (16, false) => Self::U128(u128::from_le_bytes(bytes.try_into().unwrap())),
+            (16, true) => Self::I128(i128::from_le_bytes(bytes.try_into().unwrap())),
+            _ => panic!("invalid integer size"),
+        }
+    }
+
+    fn to_bytes(self) -> Vec<u8> {
+        macro_rules! m {
+            ( [] $( $int_ty:ident )+ ) => {
+                match self {
+                    $( Self::$int_ty(v) => v.to_le_bytes().to_vec() ),+
+                }
+            };
+        }
+        for_each_int_type! { m, [] }
+    }
+
+    fn as_u32(self) -> Option<u32> {
+        macro_rules! m {
+            ( [] $( $int_ty:ident )+ ) => {
+                match self {
+                    $( Self::$int_ty(v) => v.try_into().ok() ),+
+                }
+            };
+        }
+        for_each_int_type! { m, [] }
+    }
+
+    for_each_int_type!(checked_int_op, [checked_add]);
+    for_each_int_type!(checked_int_op, [checked_sub]);
+    for_each_int_type!(checked_int_op, [checked_div]);
+    for_each_int_type!(checked_int_op, [checked_rem]);
+    for_each_int_type!(checked_int_op, [checked_mul]);
+
+    for_each_int_type!(int_bit_shifts, [checked_shl]);
+    for_each_int_type!(int_bit_shifts, [checked_shr]);
+}
+
+impl std::ops::BitAnd for IntValue {
+    type Output = Self;
+    for_each_int_type!(unchecked_int_op, [bitand, &]);
+}
+impl std::ops::BitOr for IntValue {
+    type Output = Self;
+    for_each_int_type!(unchecked_int_op, [bitor, |]);
+}
+impl std::ops::BitXor for IntValue {
+    type Output = Self;
+    for_each_int_type!(unchecked_int_op, [bitxor, ^]);
+}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs
index 30d11373732..ce43e90df7d 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs
@@ -879,3 +879,32 @@ fn main() {
 "#,
     );
 }
+
+#[test]
+fn long_str_eq_same_prefix() {
+    check_pass_and_stdio(
+        r#"
+//- minicore: slice, index, coerce_unsized
+
+type pthread_key_t = u32;
+type c_void = u8;
+type c_int = i32;
+
+extern "C" {
+    pub fn write(fd: i32, buf: *const u8, count: usize) -> usize;
+}
+
+fn main() {
+    // More than 16 bytes, the size of `i128`.
+    let long_str = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab";
+    let output = match long_str {
+        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" => b"true" as &[u8],
+        _ => b"false",
+    };
+    write(1, &output[0], output.len());
+}
+        "#,
+        "false",
+        "",
+    );
+}
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 cabeeea2bd8..b7607b5f639 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests.rs
@@ -127,7 +127,15 @@ fn check_impl(ra_fixture: &str, allow_none: bool, only_types: bool, display_sour
             None => continue,
         };
         let def_map = module.def_map(&db);
-        visit_module(&db, &def_map, module.local_id, &mut |it| defs.push(it));
+        visit_module(&db, &def_map, module.local_id, &mut |it| {
+            defs.push(match it {
+                ModuleDefId::FunctionId(it) => it.into(),
+                ModuleDefId::EnumVariantId(it) => it.into(),
+                ModuleDefId::ConstId(it) => it.into(),
+                ModuleDefId::StaticId(it) => it.into(),
+                _ => return,
+            })
+        });
     }
     defs.sort_by_key(|def| match def {
         DefWithBodyId::FunctionId(it) => {
@@ -375,7 +383,15 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
     let def_map = module.def_map(&db);
 
     let mut defs: Vec<DefWithBodyId> = Vec::new();
-    visit_module(&db, &def_map, module.local_id, &mut |it| defs.push(it));
+    visit_module(&db, &def_map, module.local_id, &mut |it| {
+        defs.push(match it {
+            ModuleDefId::FunctionId(it) => it.into(),
+            ModuleDefId::EnumVariantId(it) => it.into(),
+            ModuleDefId::ConstId(it) => it.into(),
+            ModuleDefId::StaticId(it) => it.into(),
+            _ => return,
+        })
+    });
     defs.sort_by_key(|def| match def {
         DefWithBodyId::FunctionId(it) => {
             let loc = it.lookup(&db);
@@ -405,11 +421,11 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
     buf
 }
 
-fn visit_module(
+pub(crate) fn visit_module(
     db: &TestDB,
     crate_def_map: &DefMap,
     module_id: LocalModuleId,
-    cb: &mut dyn FnMut(DefWithBodyId),
+    cb: &mut dyn FnMut(ModuleDefId),
 ) {
     visit_scope(db, crate_def_map, &crate_def_map[module_id].scope, cb);
     for impl_id in crate_def_map[module_id].scope.impls() {
@@ -417,18 +433,18 @@ fn visit_module(
         for &item in impl_data.items.iter() {
             match item {
                 AssocItemId::FunctionId(it) => {
-                    let def = it.into();
-                    cb(def);
-                    let body = db.body(def);
+                    let body = db.body(it.into());
+                    cb(it.into());
                     visit_body(db, &body, cb);
                 }
                 AssocItemId::ConstId(it) => {
-                    let def = it.into();
-                    cb(def);
-                    let body = db.body(def);
+                    let body = db.body(it.into());
+                    cb(it.into());
                     visit_body(db, &body, cb);
                 }
-                AssocItemId::TypeAliasId(_) => (),
+                AssocItemId::TypeAliasId(it) => {
+                    cb(it.into());
+                }
             }
         }
     }
@@ -437,33 +453,27 @@ fn visit_module(
         db: &TestDB,
         crate_def_map: &DefMap,
         scope: &ItemScope,
-        cb: &mut dyn FnMut(DefWithBodyId),
+        cb: &mut dyn FnMut(ModuleDefId),
     ) {
         for decl in scope.declarations() {
+            cb(decl);
             match decl {
                 ModuleDefId::FunctionId(it) => {
-                    let def = it.into();
-                    cb(def);
-                    let body = db.body(def);
+                    let body = db.body(it.into());
                     visit_body(db, &body, cb);
                 }
                 ModuleDefId::ConstId(it) => {
-                    let def = it.into();
-                    cb(def);
-                    let body = db.body(def);
+                    let body = db.body(it.into());
                     visit_body(db, &body, cb);
                 }
                 ModuleDefId::StaticId(it) => {
-                    let def = it.into();
-                    cb(def);
-                    let body = db.body(def);
+                    let body = db.body(it.into());
                     visit_body(db, &body, cb);
                 }
                 ModuleDefId::AdtId(hir_def::AdtId::EnumId(it)) => {
                     db.enum_data(it).variants.iter().for_each(|&(it, _)| {
-                        let def = it.into();
-                        cb(def);
-                        let body = db.body(def);
+                        let body = db.body(it.into());
+                        cb(it.into());
                         visit_body(db, &body, cb);
                     });
                 }
@@ -473,7 +483,7 @@ fn visit_module(
                         match item {
                             AssocItemId::FunctionId(it) => cb(it.into()),
                             AssocItemId::ConstId(it) => cb(it.into()),
-                            AssocItemId::TypeAliasId(_) => (),
+                            AssocItemId::TypeAliasId(it) => cb(it.into()),
                         }
                     }
                 }
@@ -483,7 +493,7 @@ fn visit_module(
         }
     }
 
-    fn visit_body(db: &TestDB, body: &Body, cb: &mut dyn FnMut(DefWithBodyId)) {
+    fn visit_body(db: &TestDB, body: &Body, cb: &mut dyn FnMut(ModuleDefId)) {
         for (_, def_map) in body.blocks(db) {
             for (mod_id, _) in def_map.modules() {
                 visit_module(db, &def_map, mod_id, cb);
@@ -553,7 +563,13 @@ fn salsa_bug() {
     let module = db.module_for_file(pos.file_id);
     let crate_def_map = module.def_map(&db);
     visit_module(&db, &crate_def_map, module.local_id, &mut |def| {
-        db.infer(def);
+        db.infer(match def {
+            ModuleDefId::FunctionId(it) => it.into(),
+            ModuleDefId::EnumVariantId(it) => it.into(),
+            ModuleDefId::ConstId(it) => it.into(),
+            ModuleDefId::StaticId(it) => it.into(),
+            _ => return,
+        });
     });
 
     let new_text = "
@@ -586,6 +602,12 @@ fn salsa_bug() {
     let module = db.module_for_file(pos.file_id);
     let crate_def_map = module.def_map(&db);
     visit_module(&db, &crate_def_map, module.local_id, &mut |def| {
-        db.infer(def);
+        db.infer(match def {
+            ModuleDefId::FunctionId(it) => it.into(),
+            ModuleDefId::EnumVariantId(it) => it.into(),
+            ModuleDefId::ConstId(it) => it.into(),
+            ModuleDefId::StaticId(it) => it.into(),
+            _ => return,
+        });
     });
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs
index b63d632dd26..7de92d6b160 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/closure_captures.rs
@@ -24,6 +24,13 @@ fn check_closure_captures(ra_fixture: &str, expect: Expect) {
 
     let mut captures_info = Vec::new();
     for def in defs {
+        let def = match def {
+            hir_def::ModuleDefId::FunctionId(it) => it.into(),
+            hir_def::ModuleDefId::EnumVariantId(it) => it.into(),
+            hir_def::ModuleDefId::ConstId(it) => it.into(),
+            hir_def::ModuleDefId::StaticId(it) => it.into(),
+            _ => continue,
+        };
         let infer = db.infer(def);
         let db = &db;
         captures_info.extend(infer.closure_info.iter().flat_map(|(closure_id, (captures, _))| {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs
index 0a24eeb1fe8..3757d722ac8 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs
@@ -1,4 +1,5 @@
 use base_db::SourceDatabaseFileInputExt as _;
+use hir_def::ModuleDefId;
 use test_fixture::WithFixture;
 
 use crate::{db::HirDatabase, test_db::TestDB};
@@ -19,7 +20,9 @@ fn foo() -> i32 {
             let module = db.module_for_file(pos.file_id.file_id());
             let crate_def_map = module.def_map(&db);
             visit_module(&db, &crate_def_map, module.local_id, &mut |def| {
-                db.infer(def);
+                if let ModuleDefId::FunctionId(it) = def {
+                    db.infer(it.into());
+                }
             });
         });
         assert!(format!("{events:?}").contains("infer"))
@@ -39,7 +42,9 @@ fn foo() -> i32 {
             let module = db.module_for_file(pos.file_id.file_id());
             let crate_def_map = module.def_map(&db);
             visit_module(&db, &crate_def_map, module.local_id, &mut |def| {
-                db.infer(def);
+                if let ModuleDefId::FunctionId(it) = def {
+                    db.infer(it.into());
+                }
             });
         });
         assert!(!format!("{events:?}").contains("infer"), "{events:#?}")
@@ -66,7 +71,9 @@ fn baz() -> i32 {
             let module = db.module_for_file(pos.file_id.file_id());
             let crate_def_map = module.def_map(&db);
             visit_module(&db, &crate_def_map, module.local_id, &mut |def| {
-                db.infer(def);
+                if let ModuleDefId::FunctionId(it) = def {
+                    db.infer(it.into());
+                }
             });
         });
         assert!(format!("{events:?}").contains("infer"))
@@ -91,7 +98,9 @@ fn baz() -> i32 {
             let module = db.module_for_file(pos.file_id.file_id());
             let crate_def_map = module.def_map(&db);
             visit_module(&db, &crate_def_map, module.local_id, &mut |def| {
-                db.infer(def);
+                if let ModuleDefId::FunctionId(it) = def {
+                    db.infer(it.into());
+                }
             });
         });
         assert!(format!("{events:?}").matches("infer").count() == 1, "{events:#?}")
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 42e7edaf0f4..bf7892f69bd 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
@@ -270,17 +270,15 @@ pub fn is_fn_unsafe_to_call(db: &dyn HirDatabase, func: FunctionId) -> bool {
         return true;
     }
 
-    let is_intrinsic = db.attrs(func.into()).by_key(&sym::rustc_intrinsic).exists()
-        || data.abi.as_ref() == Some(&sym::rust_dash_intrinsic);
-
     let loc = func.lookup(db.upcast());
     match loc.container {
         hir_def::ItemContainerId::ExternBlockId(block) => {
-            if is_intrinsic || {
-                let id = block.lookup(db.upcast()).id;
-                id.item_tree(db.upcast())[id.value].abi.as_ref() == Some(&sym::rust_dash_intrinsic)
-            } {
-                // Intrinsics are unsafe unless they have the rustc_safe_intrinsic attribute
+            let id = block.lookup(db.upcast()).id;
+            let is_intrinsic_block =
+                id.item_tree(db.upcast())[id.value].abi.as_ref() == Some(&sym::rust_dash_intrinsic);
+            if is_intrinsic_block {
+                // legacy intrinsics
+                // extern "rust-intrinsic" intrinsics are unsafe unless they have the rustc_safe_intrinsic attribute
                 !db.attrs(func.into()).by_key(&sym::rustc_safe_intrinsic).exists()
             } else {
                 // Function in an `extern` block are always unsafe to call, except when
@@ -288,7 +286,6 @@ pub fn is_fn_unsafe_to_call(db: &dyn HirDatabase, func: FunctionId) -> bool {
                 !data.is_safe()
             }
         }
-        _ if is_intrinsic => !db.attrs(func.into()).by_key(&sym::rustc_safe_intrinsic).exists(),
         _ => false,
     }
 }
@@ -376,7 +373,7 @@ impl OpaqueInternableThing for InTypeConstIdMetadata {
     }
 
     fn dyn_eq(&self, other: &dyn OpaqueInternableThing) -> bool {
-        other.as_any().downcast_ref::<Self>().map_or(false, |x| self == x)
+        other.as_any().downcast_ref::<Self>() == Some(self)
     }
 
     fn dyn_clone(&self) -> Box<dyn OpaqueInternableThing> {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs
new file mode 100644
index 00000000000..30711b16dfb
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs
@@ -0,0 +1,1065 @@
+//! Module for inferring the variance of type and lifetime parameters. See the [rustc dev guide]
+//! chapter for more info.
+//!
+//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/variance.html
+//!
+//! The implementation here differs from rustc. Rustc does a crate wide fixpoint resolution
+//! as the algorithm for determining variance is a fixpoint computation with potential cycles that
+//! need to be resolved. rust-analyzer does not want a crate-wide analysis though as that would hurt
+//! incrementality too much and as such our query is based on a per item basis.
+//!
+//! This does unfortunately run into the issue that we can run into query cycles which salsa
+//! currently does not allow to be resolved via a fixpoint computation. This will likely be resolved
+//! by the next salsa version. If not, we will likely have to adapt and go with the rustc approach
+//! while installing firewall per item queries to prevent invalidation issues.
+
+use crate::db::HirDatabase;
+use crate::generics::{generics, Generics};
+use crate::{
+    AliasTy, Const, ConstScalar, DynTyExt, GenericArg, GenericArgData, Interner, Lifetime,
+    LifetimeData, Ty, TyKind,
+};
+use base_db::ra_salsa::Cycle;
+use chalk_ir::Mutability;
+use hir_def::data::adt::StructFlags;
+use hir_def::{AdtId, GenericDefId, GenericParamId, VariantId};
+use std::fmt;
+use std::ops::Not;
+use stdx::never;
+use triomphe::Arc;
+
+pub(crate) fn variances_of(db: &dyn HirDatabase, def: GenericDefId) -> Option<Arc<[Variance]>> {
+    tracing::debug!("variances_of(def={:?})", def);
+    match def {
+        GenericDefId::FunctionId(_) => (),
+        GenericDefId::AdtId(adt) => {
+            if let AdtId::StructId(id) = adt {
+                let flags = &db.struct_data(id).flags;
+                if flags.contains(StructFlags::IS_UNSAFE_CELL) {
+                    return Some(Arc::from_iter(vec![Variance::Invariant; 1]));
+                } else if flags.contains(StructFlags::IS_PHANTOM_DATA) {
+                    return Some(Arc::from_iter(vec![Variance::Covariant; 1]));
+                }
+            }
+        }
+        _ => return None,
+    }
+
+    let generics = generics(db.upcast(), def);
+    let count = generics.len();
+    if count == 0 {
+        return None;
+    }
+    let variances = Context { generics, variances: vec![Variance::Bivariant; count], db }.solve();
+
+    variances.is_empty().not().then(|| Arc::from_iter(variances))
+}
+
+pub(crate) fn variances_of_cycle(
+    db: &dyn HirDatabase,
+    _cycle: &Cycle,
+    def: &GenericDefId,
+) -> Option<Arc<[Variance]>> {
+    let generics = generics(db.upcast(), *def);
+    let count = generics.len();
+
+    if count == 0 {
+        return None;
+    }
+    Some(Arc::from(vec![Variance::Bivariant; count]))
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub enum Variance {
+    Covariant,     // T<A> <: T<B> iff A <: B -- e.g., function return type
+    Invariant,     // T<A> <: T<B> iff B == A -- e.g., type of mutable cell
+    Contravariant, // T<A> <: T<B> iff B <: A -- e.g., function param type
+    Bivariant,     // T<A> <: T<B>            -- e.g., unused type parameter
+}
+
+impl fmt::Display for Variance {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Variance::Covariant => write!(f, "covariant"),
+            Variance::Invariant => write!(f, "invariant"),
+            Variance::Contravariant => write!(f, "contravariant"),
+            Variance::Bivariant => write!(f, "bivariant"),
+        }
+    }
+}
+
+impl Variance {
+    /// `a.xform(b)` combines the variance of a context with the
+    /// variance of a type with the following meaning. If we are in a
+    /// context with variance `a`, and we encounter a type argument in
+    /// a position with variance `b`, then `a.xform(b)` is the new
+    /// variance with which the argument appears.
+    ///
+    /// Example 1:
+    /// ```ignore (illustrative)
+    /// *mut Vec<i32>
+    /// ```
+    /// Here, the "ambient" variance starts as covariant. `*mut T` is
+    /// invariant with respect to `T`, so the variance in which the
+    /// `Vec<i32>` appears is `Covariant.xform(Invariant)`, which
+    /// yields `Invariant`. Now, the type `Vec<T>` is covariant with
+    /// respect to its type argument `T`, and hence the variance of
+    /// the `i32` here is `Invariant.xform(Covariant)`, which results
+    /// (again) in `Invariant`.
+    ///
+    /// Example 2:
+    /// ```ignore (illustrative)
+    /// fn(*const Vec<i32>, *mut Vec<i32)
+    /// ```
+    /// The ambient variance is covariant. A `fn` type is
+    /// contravariant with respect to its parameters, so the variance
+    /// within which both pointer types appear is
+    /// `Covariant.xform(Contravariant)`, or `Contravariant`. `*const
+    /// T` is covariant with respect to `T`, so the variance within
+    /// which the first `Vec<i32>` appears is
+    /// `Contravariant.xform(Covariant)` or `Contravariant`. The same
+    /// is true for its `i32` argument. In the `*mut T` case, the
+    /// variance of `Vec<i32>` is `Contravariant.xform(Invariant)`,
+    /// and hence the outermost type is `Invariant` with respect to
+    /// `Vec<i32>` (and its `i32` argument).
+    ///
+    /// Source: Figure 1 of "Taming the Wildcards:
+    /// Combining Definition- and Use-Site Variance" published in PLDI'11.
+    fn xform(self, v: Variance) -> Variance {
+        match (self, v) {
+            // Figure 1, column 1.
+            (Variance::Covariant, Variance::Covariant) => Variance::Covariant,
+            (Variance::Covariant, Variance::Contravariant) => Variance::Contravariant,
+            (Variance::Covariant, Variance::Invariant) => Variance::Invariant,
+            (Variance::Covariant, Variance::Bivariant) => Variance::Bivariant,
+
+            // Figure 1, column 2.
+            (Variance::Contravariant, Variance::Covariant) => Variance::Contravariant,
+            (Variance::Contravariant, Variance::Contravariant) => Variance::Covariant,
+            (Variance::Contravariant, Variance::Invariant) => Variance::Invariant,
+            (Variance::Contravariant, Variance::Bivariant) => Variance::Bivariant,
+
+            // Figure 1, column 3.
+            (Variance::Invariant, _) => Variance::Invariant,
+
+            // Figure 1, column 4.
+            (Variance::Bivariant, _) => Variance::Bivariant,
+        }
+    }
+
+    fn glb(self, v: Variance) -> Variance {
+        // Greatest lower bound of the variance lattice as
+        // defined in The Paper:
+        //
+        //       *
+        //    -     +
+        //       o
+        match (self, v) {
+            (Variance::Invariant, _) | (_, Variance::Invariant) => Variance::Invariant,
+
+            (Variance::Covariant, Variance::Contravariant) => Variance::Invariant,
+            (Variance::Contravariant, Variance::Covariant) => Variance::Invariant,
+
+            (Variance::Covariant, Variance::Covariant) => Variance::Covariant,
+
+            (Variance::Contravariant, Variance::Contravariant) => Variance::Contravariant,
+
+            (x, Variance::Bivariant) | (Variance::Bivariant, x) => x,
+        }
+    }
+
+    pub fn invariant(self) -> Self {
+        self.xform(Variance::Invariant)
+    }
+
+    pub fn covariant(self) -> Self {
+        self.xform(Variance::Covariant)
+    }
+
+    pub fn contravariant(self) -> Self {
+        self.xform(Variance::Contravariant)
+    }
+}
+
+struct Context<'db> {
+    db: &'db dyn HirDatabase,
+    generics: Generics,
+    variances: Vec<Variance>,
+}
+
+impl Context<'_> {
+    fn solve(mut self) -> Vec<Variance> {
+        tracing::debug!("solve(generics={:?})", self.generics);
+        match self.generics.def() {
+            GenericDefId::AdtId(adt) => {
+                let db = self.db;
+                let mut add_constraints_from_variant = |variant| {
+                    let subst = self.generics.placeholder_subst(db);
+                    for (_, field) in db.field_types(variant).iter() {
+                        self.add_constraints_from_ty(
+                            &field.clone().substitute(Interner, &subst),
+                            Variance::Covariant,
+                        );
+                    }
+                };
+                match adt {
+                    AdtId::StructId(s) => add_constraints_from_variant(VariantId::StructId(s)),
+                    AdtId::UnionId(u) => add_constraints_from_variant(VariantId::UnionId(u)),
+                    AdtId::EnumId(e) => {
+                        db.enum_data(e).variants.iter().for_each(|&(variant, _)| {
+                            add_constraints_from_variant(VariantId::EnumVariantId(variant))
+                        });
+                    }
+                }
+            }
+            GenericDefId::FunctionId(f) => {
+                let subst = self.generics.placeholder_subst(self.db);
+                self.add_constraints_from_sig(
+                    self.db
+                        .callable_item_signature(f.into())
+                        .substitute(Interner, &subst)
+                        .params_and_return
+                        .iter(),
+                    Variance::Covariant,
+                );
+            }
+            _ => {}
+        }
+        let mut variances = self.variances;
+
+        // Const parameters are always invariant.
+        // Make all const parameters invariant.
+        for (idx, param) in self.generics.iter_id().enumerate() {
+            if let GenericParamId::ConstParamId(_) = param {
+                variances[idx] = Variance::Invariant;
+            }
+        }
+
+        // Functions are permitted to have unused generic parameters: make those invariant.
+        if let GenericDefId::FunctionId(_) = self.generics.def() {
+            variances
+                .iter_mut()
+                .filter(|&&mut v| v == Variance::Bivariant)
+                .for_each(|v| *v = Variance::Invariant);
+        }
+
+        variances
+    }
+
+    /// Adds constraints appropriate for an instance of `ty` appearing
+    /// in a context with the generics defined in `generics` and
+    /// ambient variance `variance`
+    fn add_constraints_from_ty(&mut self, ty: &Ty, variance: Variance) {
+        tracing::debug!("add_constraints_from_ty(ty={:?}, variance={:?})", ty, variance);
+        match ty.kind(Interner) {
+            TyKind::Scalar(_) | TyKind::Never | TyKind::Str | TyKind::Foreign(..) => {
+                // leaf type -- noop
+            }
+            TyKind::FnDef(..) | TyKind::Coroutine(..) | TyKind::Closure(..) => {
+                never!("Unexpected unnameable type in variance computation: {:?}", ty);
+            }
+            TyKind::Ref(mutbl, lifetime, ty) => {
+                self.add_constraints_from_region(lifetime, variance);
+                self.add_constraints_from_mt(ty, *mutbl, variance);
+            }
+            TyKind::Array(typ, len) => {
+                self.add_constraints_from_const(len, variance);
+                self.add_constraints_from_ty(typ, variance);
+            }
+            TyKind::Slice(typ) => {
+                self.add_constraints_from_ty(typ, variance);
+            }
+            TyKind::Raw(mutbl, ty) => {
+                self.add_constraints_from_mt(ty, *mutbl, variance);
+            }
+            TyKind::Tuple(_, subtys) => {
+                for subty in subtys.type_parameters(Interner) {
+                    self.add_constraints_from_ty(&subty, variance);
+                }
+            }
+            TyKind::Adt(def, args) => {
+                self.add_constraints_from_args(def.0.into(), args.as_slice(Interner), variance);
+            }
+            TyKind::Alias(AliasTy::Opaque(opaque)) => {
+                self.add_constraints_from_invariant_args(
+                    opaque.substitution.as_slice(Interner),
+                    variance,
+                );
+            }
+            TyKind::Alias(AliasTy::Projection(proj)) => {
+                self.add_constraints_from_invariant_args(
+                    proj.substitution.as_slice(Interner),
+                    variance,
+                );
+            }
+            // FIXME: check this
+            TyKind::AssociatedType(_, subst) => {
+                self.add_constraints_from_invariant_args(subst.as_slice(Interner), variance);
+            }
+            // FIXME: check this
+            TyKind::OpaqueType(_, subst) => {
+                self.add_constraints_from_invariant_args(subst.as_slice(Interner), variance);
+            }
+            TyKind::Dyn(it) => {
+                // The type `dyn Trait<T> +'a` is covariant w/r/t `'a`:
+                self.add_constraints_from_region(&it.lifetime, variance);
+
+                if let Some(trait_ref) = it.principal() {
+                    // Trait are always invariant so we can take advantage of that.
+                    self.add_constraints_from_invariant_args(
+                        trait_ref
+                            .map(|it| it.map(|it| it.substitution.clone()))
+                            .substitute(
+                                Interner,
+                                &[GenericArg::new(
+                                    Interner,
+                                    chalk_ir::GenericArgData::Ty(TyKind::Error.intern(Interner)),
+                                )],
+                            )
+                            .skip_binders()
+                            .as_slice(Interner),
+                        variance,
+                    );
+                }
+
+                // FIXME
+                // for projection in data.projection_bounds() {
+                //     match projection.skip_binder().term.unpack() {
+                //         TyKind::TermKind::Ty(ty) => {
+                //             self.add_constraints_from_ty( ty, self.invariant);
+                //         }
+                //         TyKind::TermKind::Const(c) => {
+                //             self.add_constraints_from_const( c, self.invariant)
+                //         }
+                //     }
+                // }
+            }
+
+            // Chalk has no params, so use placeholders for now?
+            TyKind::Placeholder(index) => {
+                let idx = crate::from_placeholder_idx(self.db, *index);
+                let index = self.generics.type_or_const_param_idx(idx).unwrap();
+                self.constrain(index, variance);
+            }
+            TyKind::Function(f) => {
+                self.add_constraints_from_sig(
+                    f.substitution.0.iter(Interner).filter_map(move |p| p.ty(Interner)),
+                    variance,
+                );
+            }
+            TyKind::Error => {
+                // we encounter this when walking the trait references for object
+                // types, where we use Error as the Self type
+            }
+            TyKind::CoroutineWitness(..) | TyKind::BoundVar(..) | TyKind::InferenceVar(..) => {
+                never!("unexpected type encountered in variance inference: {:?}", ty)
+            }
+        }
+    }
+
+    fn add_constraints_from_invariant_args(&mut self, args: &[GenericArg], variance: Variance) {
+        let variance_i = variance.invariant();
+
+        for k in args {
+            match k.data(Interner) {
+                GenericArgData::Lifetime(lt) => self.add_constraints_from_region(lt, variance_i),
+                GenericArgData::Ty(ty) => self.add_constraints_from_ty(ty, variance_i),
+                GenericArgData::Const(val) => self.add_constraints_from_const(val, variance_i),
+            }
+        }
+    }
+
+    /// Adds constraints appropriate for a nominal type (enum, struct,
+    /// object, etc) appearing in a context with ambient variance `variance`
+    fn add_constraints_from_args(
+        &mut self,
+        def_id: GenericDefId,
+        args: &[GenericArg],
+        variance: Variance,
+    ) {
+        // We don't record `inferred_starts` entries for empty generics.
+        if args.is_empty() {
+            return;
+        }
+        let Some(variances) = self.db.variances_of(def_id) else {
+            return;
+        };
+
+        for (i, k) in args.iter().enumerate() {
+            match k.data(Interner) {
+                GenericArgData::Lifetime(lt) => {
+                    self.add_constraints_from_region(lt, variance.xform(variances[i]))
+                }
+                GenericArgData::Ty(ty) => {
+                    self.add_constraints_from_ty(ty, variance.xform(variances[i]))
+                }
+                GenericArgData::Const(val) => self.add_constraints_from_const(val, variance),
+            }
+        }
+    }
+
+    /// Adds constraints appropriate for a const expression `val`
+    /// in a context with ambient variance `variance`
+    fn add_constraints_from_const(&mut self, c: &Const, variance: Variance) {
+        match &c.data(Interner).value {
+            chalk_ir::ConstValue::Concrete(c) => {
+                if let ConstScalar::UnevaluatedConst(_, subst) = &c.interned {
+                    self.add_constraints_from_invariant_args(subst.as_slice(Interner), variance);
+                }
+            }
+            _ => {}
+        }
+    }
+
+    /// Adds constraints appropriate for a function with signature
+    /// `sig` appearing in a context with ambient variance `variance`
+    fn add_constraints_from_sig<'a>(
+        &mut self,
+        mut sig_tys: impl DoubleEndedIterator<Item = &'a Ty>,
+        variance: Variance,
+    ) {
+        let contra = variance.contravariant();
+        let Some(output) = sig_tys.next_back() else {
+            return never!("function signature has no return type");
+        };
+        self.add_constraints_from_ty(output, variance);
+        for input in sig_tys {
+            self.add_constraints_from_ty(input, contra);
+        }
+    }
+
+    /// Adds constraints appropriate for a region appearing in a
+    /// context with ambient variance `variance`
+    fn add_constraints_from_region(&mut self, region: &Lifetime, variance: Variance) {
+        tracing::debug!(
+            "add_constraints_from_region(region={:?}, variance={:?})",
+            region,
+            variance
+        );
+        match region.data(Interner) {
+            LifetimeData::Placeholder(index) => {
+                let idx = crate::lt_from_placeholder_idx(self.db, *index);
+                let inferred = self.generics.lifetime_idx(idx).unwrap();
+                self.constrain(inferred, variance);
+            }
+            LifetimeData::Static => {}
+            LifetimeData::BoundVar(..) => {
+                // Either a higher-ranked region inside of a type or a
+                // late-bound function parameter.
+                //
+                // We do not compute constraints for either of these.
+            }
+            LifetimeData::Error => {}
+            LifetimeData::Phantom(..) | LifetimeData::InferenceVar(..) | LifetimeData::Erased => {
+                // We don't expect to see anything but 'static or bound
+                // regions when visiting member types or method types.
+                never!(
+                    "unexpected region encountered in variance \
+                      inference: {:?}",
+                    region
+                );
+            }
+        }
+    }
+
+    /// Adds constraints appropriate for a mutability-type pair
+    /// appearing in a context with ambient variance `variance`
+    fn add_constraints_from_mt(&mut self, ty: &Ty, mt: Mutability, variance: Variance) {
+        self.add_constraints_from_ty(
+            ty,
+            match mt {
+                Mutability::Mut => variance.invariant(),
+                Mutability::Not => variance,
+            },
+        );
+    }
+
+    fn constrain(&mut self, index: usize, variance: Variance) {
+        tracing::debug!(
+            "constrain(index={:?}, variance={:?}, to={:?})",
+            index,
+            self.variances[index],
+            variance
+        );
+        self.variances[index] = self.variances[index].glb(variance);
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use expect_test::{expect, Expect};
+    use hir_def::{
+        generics::GenericParamDataRef, src::HasSource, AdtId, GenericDefId, ModuleDefId,
+    };
+    use itertools::Itertools;
+    use stdx::format_to;
+    use syntax::{ast::HasName, AstNode};
+    use test_fixture::WithFixture;
+
+    use hir_def::Lookup;
+
+    use crate::{db::HirDatabase, test_db::TestDB, variance::generics};
+
+    #[test]
+    fn phantom_data() {
+        check(
+            r#"
+//- minicore: phantom_data
+
+struct Covariant<A> {
+    t: core::marker::PhantomData<A>
+}
+"#,
+            expect![[r#"
+                Covariant[A: covariant]
+            "#]],
+        );
+    }
+
+    #[test]
+    fn rustc_test_variance_types() {
+        check(
+            r#"
+//- minicore: cell
+
+use core::cell::UnsafeCell;
+
+struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR ['a: +, A: o, B: o]
+    t: &'a mut (A,B)
+}
+
+struct InvariantCell<A> { //~ ERROR [A: o]
+    t: UnsafeCell<A>
+}
+
+struct InvariantIndirect<A> { //~ ERROR [A: o]
+    t: InvariantCell<A>
+}
+
+struct Covariant<A> { //~ ERROR [A: +]
+    t: A, u: fn() -> A
+}
+
+struct Contravariant<A> { //~ ERROR [A: -]
+    t: fn(A)
+}
+
+enum Enum<A,B,C> { //~ ERROR [A: +, B: -, C: o]
+    Foo(Covariant<A>),
+    Bar(Contravariant<B>),`
+    Zed(Covariant<C>,Contravariant<C>)
+}
+"#,
+            expect![[r#"
+                InvariantMut['a: covariant, A: invariant, B: invariant]
+                InvariantCell[A: invariant]
+                InvariantIndirect[A: invariant]
+                Covariant[A: covariant]
+                Contravariant[A: contravariant]
+                Enum[A: covariant, B: contravariant, C: invariant]
+            "#]],
+        );
+    }
+
+    #[test]
+    fn type_resolve_error_two_structs_deep() {
+        check(
+            r#"
+struct Hello<'a> {
+    missing: Missing<'a>,
+}
+
+struct Other<'a> {
+    hello: Hello<'a>,
+}
+"#,
+            expect![[r#"
+                Hello['a: bivariant]
+                Other['a: bivariant]
+            "#]],
+        );
+    }
+
+    #[test]
+    fn rustc_test_variance_associated_consts() {
+        // FIXME: Should be invariant
+        check(
+            r#"
+trait Trait {
+    const Const: usize;
+}
+
+struct Foo<T: Trait> { //~ ERROR [T: o]
+    field: [u8; <T as Trait>::Const]
+}
+"#,
+            expect![[r#"
+                Foo[T: bivariant]
+            "#]],
+        );
+    }
+
+    #[test]
+    fn rustc_test_variance_associated_types() {
+        check(
+            r#"
+trait Trait<'a> {
+    type Type;
+
+    fn method(&'a self) { }
+}
+
+struct Foo<'a, T : Trait<'a>> { //~ ERROR ['a: +, T: +]
+    field: (T, &'a ())
+}
+
+struct Bar<'a, T : Trait<'a>> { //~ ERROR ['a: o, T: o]
+    field: <T as Trait<'a>>::Type
+}
+
+"#,
+            expect![[r#"
+                method[Self: contravariant, 'a: contravariant]
+                Foo['a: covariant, T: covariant]
+                Bar['a: invariant, T: invariant]
+            "#]],
+        );
+    }
+
+    #[test]
+    fn rustc_test_variance_associated_types2() {
+        // FIXME: RPITs have variance, but we can't treat them as their own thing right now
+        check(
+            r#"
+trait Foo {
+    type Bar;
+}
+
+fn make() -> *const dyn Foo<Bar = &'static u32> {}
+"#,
+            expect![""],
+        );
+    }
+
+    #[test]
+    fn rustc_test_variance_trait_bounds() {
+        check(
+            r#"
+trait Getter<T> {
+    fn get(&self) -> T;
+}
+
+trait Setter<T> {
+    fn get(&self, _: T);
+}
+
+struct TestStruct<U,T:Setter<U>> { //~ ERROR [U: +, T: +]
+    t: T, u: U
+}
+
+enum TestEnum<U,T:Setter<U>> { //~ ERROR [U: *, T: +]
+    //~^ ERROR: `U` is never used
+    Foo(T)
+}
+
+struct TestContraStruct<U,T:Setter<U>> { //~ ERROR [U: *, T: +]
+    //~^ ERROR: `U` is never used
+    t: T
+}
+
+struct TestBox<U,T:Getter<U>+Setter<U>> { //~ ERROR [U: *, T: +]
+    //~^ ERROR: `U` is never used
+    t: T
+}
+"#,
+            expect![[r#"
+                get[Self: contravariant, T: covariant]
+                get[Self: contravariant, T: contravariant]
+                TestStruct[U: covariant, T: covariant]
+                TestEnum[U: bivariant, T: covariant]
+                TestContraStruct[U: bivariant, T: covariant]
+                TestBox[U: bivariant, T: covariant]
+            "#]],
+        );
+    }
+
+    #[test]
+    fn rustc_test_variance_trait_matching() {
+        check(
+            r#"
+
+trait Get<T> {
+    fn get(&self) -> T;
+}
+
+struct Cloner<T:Clone> {
+    t: T
+}
+
+impl<T:Clone> Get<T> for Cloner<T> {
+    fn get(&self) -> T {}
+}
+
+fn get<'a, G>(get: &G) -> i32
+    where G : Get<&'a i32>
+{}
+
+fn pick<'b, G>(get: &'b G, if_odd: &'b i32) -> i32
+    where G : Get<&'b i32>
+{}
+"#,
+            expect![[r#"
+                get[Self: contravariant, T: covariant]
+                Cloner[T: covariant]
+                get[T: invariant]
+                get['a: invariant, G: contravariant]
+                pick['b: contravariant, G: contravariant]
+            "#]],
+        );
+    }
+
+    #[test]
+    fn rustc_test_variance_trait_object_bound() {
+        check(
+            r#"
+enum Option<T> {
+    Some(T),
+    None
+}
+trait T { fn foo(&self); }
+
+struct TOption<'a> { //~ ERROR ['a: +]
+    v: Option<*const (dyn T + 'a)>,
+}
+"#,
+            expect![[r#"
+                Option[T: covariant]
+                foo[Self: contravariant]
+                TOption['a: covariant]
+            "#]],
+        );
+    }
+
+    #[test]
+    fn rustc_test_variance_types_bounds() {
+        check(
+            r#"
+//- minicore: send
+struct TestImm<A, B> { //~ ERROR [A: +, B: +]
+    x: A,
+    y: B,
+}
+
+struct TestMut<A, B:'static> { //~ ERROR [A: +, B: o]
+    x: A,
+    y: &'static mut B,
+}
+
+struct TestIndirect<A:'static, B:'static> { //~ ERROR [A: +, B: o]
+    m: TestMut<A, B>
+}
+
+struct TestIndirect2<A:'static, B:'static> { //~ ERROR [A: o, B: o]
+    n: TestMut<A, B>,
+    m: TestMut<B, A>
+}
+
+trait Getter<A> {
+    fn get(&self) -> A;
+}
+
+trait Setter<A> {
+    fn set(&mut self, a: A);
+}
+
+struct TestObject<A, R> { //~ ERROR [A: o, R: o]
+    n: *const (dyn Setter<A> + Send),
+    m: *const (dyn Getter<R> + Send),
+}
+"#,
+            expect![[r#"
+                TestImm[A: covariant, B: covariant]
+                TestMut[A: covariant, B: invariant]
+                TestIndirect[A: covariant, B: invariant]
+                TestIndirect2[A: invariant, B: invariant]
+                get[Self: contravariant, A: covariant]
+                set[Self: invariant, A: contravariant]
+                TestObject[A: invariant, R: invariant]
+            "#]],
+        );
+    }
+
+    #[test]
+    fn rustc_test_variance_unused_region_param() {
+        check(
+            r#"
+struct SomeStruct<'a> { x: u32 } //~ ERROR parameter `'a` is never used
+enum SomeEnum<'a> { Nothing } //~ ERROR parameter `'a` is never used
+trait SomeTrait<'a> { fn foo(&self); } // OK on traits.
+"#,
+            expect![[r#"
+                SomeStruct['a: bivariant]
+                SomeEnum['a: bivariant]
+                foo[Self: contravariant, 'a: invariant]
+            "#]],
+        );
+    }
+
+    #[test]
+    fn rustc_test_variance_unused_type_param() {
+        check(
+            r#"
+//- minicore: sized
+struct SomeStruct<A> { x: u32 }
+enum SomeEnum<A> { Nothing }
+enum ListCell<T> {
+    Cons(*const ListCell<T>),
+    Nil
+}
+
+struct SelfTyAlias<T>(*const Self);
+struct WithBounds<T: Sized> {}
+struct WithWhereBounds<T> where T: Sized {}
+struct WithOutlivesBounds<T: 'static> {}
+struct DoubleNothing<T> {
+    s: SomeStruct<T>,
+}
+
+"#,
+            expect![[r#"
+                SomeStruct[A: bivariant]
+                SomeEnum[A: bivariant]
+                ListCell[T: bivariant]
+                SelfTyAlias[T: bivariant]
+                WithBounds[T: bivariant]
+                WithWhereBounds[T: bivariant]
+                WithOutlivesBounds[T: bivariant]
+                DoubleNothing[T: bivariant]
+            "#]],
+        );
+    }
+
+    #[test]
+    fn rustc_test_variance_use_contravariant_struct1() {
+        check(
+            r#"
+struct SomeStruct<T>(fn(T));
+
+fn foo<'min,'max>(v: SomeStruct<&'max ()>)
+                  -> SomeStruct<&'min ()>
+    where 'max : 'min
+{}
+"#,
+            expect![[r#"
+                SomeStruct[T: contravariant]
+                foo['min: contravariant, 'max: covariant]
+            "#]],
+        );
+    }
+
+    #[test]
+    fn rustc_test_variance_use_contravariant_struct2() {
+        check(
+            r#"
+struct SomeStruct<T>(fn(T));
+
+fn bar<'min,'max>(v: SomeStruct<&'min ()>)
+                  -> SomeStruct<&'max ()>
+    where 'max : 'min
+{}
+"#,
+            expect![[r#"
+                SomeStruct[T: contravariant]
+                bar['min: covariant, 'max: contravariant]
+            "#]],
+        );
+    }
+
+    #[test]
+    fn rustc_test_variance_use_covariant_struct1() {
+        check(
+            r#"
+struct SomeStruct<T>(T);
+
+fn foo<'min,'max>(v: SomeStruct<&'min ()>)
+                  -> SomeStruct<&'max ()>
+    where 'max : 'min
+{}
+"#,
+            expect![[r#"
+                SomeStruct[T: covariant]
+                foo['min: contravariant, 'max: covariant]
+            "#]],
+        );
+    }
+
+    #[test]
+    fn rustc_test_variance_use_covariant_struct2() {
+        check(
+            r#"
+struct SomeStruct<T>(T);
+
+fn foo<'min,'max>(v: SomeStruct<&'max ()>)
+                  -> SomeStruct<&'min ()>
+    where 'max : 'min
+{}
+"#,
+            expect![[r#"
+                SomeStruct[T: covariant]
+                foo['min: covariant, 'max: contravariant]
+            "#]],
+        );
+    }
+
+    #[test]
+    fn rustc_test_variance_use_invariant_struct1() {
+        check(
+            r#"
+struct SomeStruct<T>(*mut T);
+
+fn foo<'min,'max>(v: SomeStruct<&'max ()>)
+                  -> SomeStruct<&'min ()>
+    where 'max : 'min
+{}
+
+fn bar<'min,'max>(v: SomeStruct<&'min ()>)
+                  -> SomeStruct<&'max ()>
+    where 'max : 'min
+{}
+"#,
+            expect![[r#"
+                SomeStruct[T: invariant]
+                foo['min: invariant, 'max: invariant]
+                bar['min: invariant, 'max: invariant]
+            "#]],
+        );
+    }
+
+    #[test]
+    fn invalid_arg_counts() {
+        check(
+            r#"
+struct S<T>(T);
+struct S2<T>(S<>);
+struct S3<T>(S<T, T>);
+"#,
+            expect![[r#"
+                S[T: covariant]
+                S2[T: bivariant]
+                S3[T: covariant]
+            "#]],
+        );
+    }
+
+    #[test]
+    fn prove_fixedpoint() {
+        // FIXME: This is wrong, this should be `FixedPoint[T: covariant, U: covariant, V: covariant]`
+        // This is a limitation of current salsa where a cycle may only set a fallback value to the
+        // query result, but we need to solve a fixpoint here. The new salsa will have this
+        // fortunately.
+        check(
+            r#"
+struct FixedPoint<T, U, V>(&'static FixedPoint<(), T, U>, V);
+"#,
+            expect![[r#"
+                FixedPoint[T: bivariant, U: bivariant, V: bivariant]
+            "#]],
+        );
+    }
+
+    #[track_caller]
+    fn check(ra_fixture: &str, expected: Expect) {
+        // use tracing_subscriber::{layer::SubscriberExt, Layer};
+        // let my_layer = tracing_subscriber::fmt::layer();
+        // let _g = tracing::subscriber::set_default(tracing_subscriber::registry().with(
+        //     my_layer.with_filter(tracing_subscriber::filter::filter_fn(|metadata| {
+        //         metadata.target().starts_with("hir_ty::variance")
+        //     })),
+        // ));
+        let (db, file_id) = TestDB::with_single_file(ra_fixture);
+
+        let mut defs: Vec<GenericDefId> = Vec::new();
+        let module = db.module_for_file_opt(file_id).unwrap();
+        let def_map = module.def_map(&db);
+        crate::tests::visit_module(&db, &def_map, module.local_id, &mut |it| {
+            defs.push(match it {
+                ModuleDefId::FunctionId(it) => it.into(),
+                ModuleDefId::AdtId(it) => it.into(),
+                ModuleDefId::ConstId(it) => it.into(),
+                ModuleDefId::TraitId(it) => it.into(),
+                ModuleDefId::TraitAliasId(it) => it.into(),
+                ModuleDefId::TypeAliasId(it) => it.into(),
+                _ => return,
+            })
+        });
+        let defs = defs
+            .into_iter()
+            .filter_map(|def| {
+                Some((
+                    def,
+                    match def {
+                        GenericDefId::FunctionId(it) => {
+                            let loc = it.lookup(&db);
+                            loc.source(&db).value.name().unwrap()
+                        }
+                        GenericDefId::AdtId(AdtId::EnumId(it)) => {
+                            let loc = it.lookup(&db);
+                            loc.source(&db).value.name().unwrap()
+                        }
+                        GenericDefId::AdtId(AdtId::StructId(it)) => {
+                            let loc = it.lookup(&db);
+                            loc.source(&db).value.name().unwrap()
+                        }
+                        GenericDefId::AdtId(AdtId::UnionId(it)) => {
+                            let loc = it.lookup(&db);
+                            loc.source(&db).value.name().unwrap()
+                        }
+                        GenericDefId::TraitId(it) => {
+                            let loc = it.lookup(&db);
+                            loc.source(&db).value.name().unwrap()
+                        }
+                        GenericDefId::TraitAliasId(it) => {
+                            let loc = it.lookup(&db);
+                            loc.source(&db).value.name().unwrap()
+                        }
+                        GenericDefId::TypeAliasId(it) => {
+                            let loc = it.lookup(&db);
+                            loc.source(&db).value.name().unwrap()
+                        }
+                        GenericDefId::ImplId(_) => return None,
+                        GenericDefId::ConstId(_) => return None,
+                    },
+                ))
+            })
+            .sorted_by_key(|(_, n)| n.syntax().text_range().start());
+        let mut res = String::new();
+        for (def, name) in defs {
+            let Some(variances) = db.variances_of(def) else {
+                continue;
+            };
+            format_to!(
+                res,
+                "{name}[{}]\n",
+                generics(&db, def)
+                    .iter()
+                    .map(|(_, param)| match param {
+                        GenericParamDataRef::TypeParamData(type_param_data) => {
+                            type_param_data.name.as_ref().unwrap()
+                        }
+                        GenericParamDataRef::ConstParamData(const_param_data) =>
+                            &const_param_data.name,
+                        GenericParamDataRef::LifetimeParamData(lifetime_param_data) => {
+                            &lifetime_param_data.name
+                        }
+                    })
+                    .zip_eq(&*variances)
+                    .format_with(", ", |(name, var), f| f(&format_args!(
+                        "{}: {var}",
+                        name.as_str()
+                    )))
+            );
+        }
+
+        expected.assert_eq(&res);
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/hir/src/attrs.rs b/src/tools/rust-analyzer/crates/hir/src/attrs.rs
index af60c233e55..a23fdf1b393 100644
--- a/src/tools/rust-analyzer/crates/hir/src/attrs.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/attrs.rs
@@ -258,7 +258,7 @@ fn resolve_impl_trait_item(
         &traits_in_scope,
         method_resolution::VisibleFromModule::None,
         Some(name),
-        &mut |assoc_item_id| {
+        &mut |_, assoc_item_id: AssocItemId, _| {
             // If two traits in scope define the same item, Rustdoc links to no specific trait (for
             // instance, given two methods `a`, Rustdoc simply links to `method.a` with no
             // disambiguation) so we just pick the first one we find as well.
diff --git a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
index cbb1ed95ed6..fc77d1889c8 100644
--- a/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/diagnostics.rs
@@ -15,12 +15,12 @@ use hir_expand::{name::Name, HirFileId, InFile};
 use hir_ty::{
     db::HirDatabase,
     diagnostics::{BodyValidationDiagnostic, UnsafetyReason},
-    CastError, InferenceDiagnostic, InferenceTyDiagnosticSource, TyLoweringDiagnostic,
-    TyLoweringDiagnosticKind,
+    CastError, InferenceDiagnostic, InferenceTyDiagnosticSource, PathLoweringDiagnostic,
+    TyLoweringDiagnostic, TyLoweringDiagnosticKind,
 };
 use syntax::{
     ast::{self, HasGenericArgs},
-    AstPtr, SyntaxError, SyntaxNodePtr, TextRange,
+    match_ast, AstNode, AstPtr, SyntaxError, SyntaxNodePtr, TextRange,
 };
 use triomphe::Arc;
 
@@ -674,6 +674,39 @@ impl AnyDiagnostic {
                 };
                 Self::ty_diagnostic(diag, source_map, db)?
             }
+            InferenceDiagnostic::PathDiagnostic { node, diag } => {
+                let source = expr_or_pat_syntax(*node)?;
+                let syntax = source.value.to_node(&db.parse_or_expand(source.file_id));
+                let path = match_ast! {
+                    match (syntax.syntax()) {
+                        ast::RecordExpr(it) => it.path()?,
+                        ast::RecordPat(it) => it.path()?,
+                        ast::TupleStructPat(it) => it.path()?,
+                        ast::PathExpr(it) => it.path()?,
+                        ast::PathPat(it) => it.path()?,
+                        _ => return None,
+                    }
+                };
+                Self::path_diagnostic(diag, source.with_value(path))?
+            }
+        })
+    }
+
+    fn path_diagnostic(
+        diag: &PathLoweringDiagnostic,
+        path: InFile<ast::Path>,
+    ) -> Option<AnyDiagnostic> {
+        Some(match diag {
+            &PathLoweringDiagnostic::GenericArgsProhibited { segment, reason } => {
+                let segment = hir_segment_to_ast_segment(&path.value, segment)?;
+                let args = if let Some(generics) = segment.generic_arg_list() {
+                    AstPtr::new(&generics).wrap_left()
+                } else {
+                    AstPtr::new(&segment.parenthesized_arg_list()?).wrap_right()
+                };
+                let args = path.with_value(args);
+                GenericArgsProhibited { args, reason }.into()
+            }
         })
     }
 
@@ -693,17 +726,10 @@ impl AnyDiagnostic {
             Either::Right(source) => source,
         };
         let syntax = || source.value.to_node(&db.parse_or_expand(source.file_id));
-        Some(match diag.kind {
-            TyLoweringDiagnosticKind::GenericArgsProhibited { segment, reason } => {
+        Some(match &diag.kind {
+            TyLoweringDiagnosticKind::PathDiagnostic(diag) => {
                 let ast::Type::PathType(syntax) = syntax() else { return None };
-                let segment = hir_segment_to_ast_segment(&syntax.path()?, segment)?;
-                let args = if let Some(generics) = segment.generic_arg_list() {
-                    AstPtr::new(&generics).wrap_left()
-                } else {
-                    AstPtr::new(&segment.parenthesized_arg_list()?).wrap_right()
-                };
-                let args = source.with_value(args);
-                GenericArgsProhibited { args, reason }.into()
+                Self::path_diagnostic(diag, source.with_value(syntax.path()?))?
             }
         })
     }
diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs
index 959d62d5951..e09ded32fbd 100644
--- a/src/tools/rust-analyzer/crates/hir/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/display.rs
@@ -1,7 +1,10 @@
 //! HirDisplay implementations for various hir types.
 use either::Either;
 use hir_def::{
-    data::adt::{StructKind, VariantData},
+    data::{
+        adt::{StructKind, VariantData},
+        TraitFlags,
+    },
     generics::{
         GenericParams, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
         WherePredicateTypeTarget,
@@ -22,7 +25,7 @@ use itertools::Itertools;
 use crate::{
     Adt, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl,
     Field, Function, GenericParam, HasCrate, HasVisibility, Impl, LifetimeParam, Macro, Module,
-    SelfParam, Static, Struct, Trait, TraitAlias, TupleField, TyBuilder, Type, TypeAlias,
+    SelfParam, Static, Struct, Trait, TraitAlias, TraitRef, TupleField, TyBuilder, Type, TypeAlias,
     TypeOrConstParam, TypeParam, Union, Variant,
 };
 
@@ -743,6 +746,12 @@ impl HirDisplay for Static {
     }
 }
 
+impl HirDisplay for TraitRef {
+    fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
+        self.trait_ref.hir_fmt(f)
+    }
+}
+
 impl HirDisplay for Trait {
     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
         write_trait_header(self, f)?;
@@ -785,10 +794,10 @@ impl HirDisplay for Trait {
 fn write_trait_header(trait_: &Trait, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
     write_visibility(trait_.module(f.db).id, trait_.visibility(f.db), f)?;
     let data = f.db.trait_data(trait_.id);
-    if data.is_unsafe {
+    if data.flags.contains(TraitFlags::IS_UNSAFE) {
         f.write_str("unsafe ")?;
     }
-    if data.is_auto {
+    if data.flags.contains(TraitFlags::IS_AUTO) {
         f.write_str("auto ")?;
     }
     write!(f, "trait {}", data.name.display(f.db.upcast(), f.edition()))?;
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index dfc91c73433..00b4db54374 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -43,7 +43,7 @@ use base_db::{CrateDisplayName, CrateId, CrateOrigin};
 use either::Either;
 use hir_def::{
     body::BodyDiagnostic,
-    data::adt::VariantData,
+    data::{adt::VariantData, TraitFlags},
     generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
     hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, Pat},
     item_tree::{AttrOwner, FieldParent, ItemTreeFieldId, ItemTreeNode},
@@ -101,7 +101,6 @@ pub use crate::{
         PathResolution, Semantics, SemanticsImpl, SemanticsScope, TypeInfo, VisibleTraits,
     },
 };
-pub use hir_ty::method_resolution::TyFingerprint;
 
 // Be careful with these re-exports.
 //
@@ -151,8 +150,9 @@ pub use {
         display::{ClosureStyle, HirDisplay, HirDisplayError, HirWrite},
         dyn_compatibility::{DynCompatibilityViolation, MethodViolationCode},
         layout::LayoutError,
+        method_resolution::TyFingerprint,
         mir::{MirEvalError, MirLowerError},
-        CastError, FnAbi, PointerCast, Safety,
+        CastError, FnAbi, PointerCast, Safety, Variance,
     },
     // FIXME: Properly encapsulate mir
     hir_ty::{mir, Interner as ChalkTyInterner},
@@ -699,7 +699,7 @@ impl Module {
             let source_map = tree_source_maps.impl_(loc.id.value).item();
             let node = &tree[loc.id.value];
             let file_id = loc.id.file_id();
-            if file_id.macro_file().map_or(false, |it| it.is_builtin_derive(db.upcast())) {
+            if file_id.macro_file().is_some_and(|it| it.is_builtin_derive(db.upcast())) {
                 // these expansion come from us, diagnosing them is a waste of resources
                 // FIXME: Once we diagnose the inputs to builtin derives, we should at least extract those diagnostics somehow
                 continue;
@@ -724,7 +724,7 @@ impl Module {
             }
 
             let trait_ = impl_def.trait_(db);
-            let trait_is_unsafe = trait_.map_or(false, |t| t.is_unsafe(db));
+            let trait_is_unsafe = trait_.is_some_and(|t| t.is_unsafe(db));
             let impl_is_negative = impl_def.is_negative(db);
             let impl_is_unsafe = impl_def.is_unsafe(db);
 
@@ -2778,11 +2778,11 @@ impl Trait {
     }
 
     pub fn is_auto(self, db: &dyn HirDatabase) -> bool {
-        db.trait_data(self.id).is_auto
+        db.trait_data(self.id).flags.contains(TraitFlags::IS_AUTO)
     }
 
     pub fn is_unsafe(&self, db: &dyn HirDatabase) -> bool {
-        db.trait_data(self.id).is_unsafe
+        db.trait_data(self.id).flags.contains(TraitFlags::IS_UNSAFE)
     }
 
     pub fn type_or_const_param_count(
@@ -3574,6 +3574,61 @@ impl GenericDef {
     }
 }
 
+// We cannot call this `Substitution` unfortunately...
+#[derive(Debug)]
+pub struct GenericSubstitution {
+    def: GenericDefId,
+    subst: Substitution,
+    env: Arc<TraitEnvironment>,
+}
+
+impl GenericSubstitution {
+    fn new(def: GenericDefId, subst: Substitution, env: Arc<TraitEnvironment>) -> Self {
+        Self { def, subst, env }
+    }
+
+    pub fn types(&self, db: &dyn HirDatabase) -> Vec<(Symbol, Type)> {
+        let container = match self.def {
+            GenericDefId::ConstId(id) => Some(id.lookup(db.upcast()).container),
+            GenericDefId::FunctionId(id) => Some(id.lookup(db.upcast()).container),
+            GenericDefId::TypeAliasId(id) => Some(id.lookup(db.upcast()).container),
+            _ => None,
+        };
+        let container_type_params = container
+            .and_then(|container| match container {
+                ItemContainerId::ImplId(container) => Some(container.into()),
+                ItemContainerId::TraitId(container) => Some(container.into()),
+                _ => None,
+            })
+            .map(|container| {
+                db.generic_params(container)
+                    .iter_type_or_consts()
+                    .filter_map(|param| match param.1 {
+                        TypeOrConstParamData::TypeParamData(param) => Some(param.name.clone()),
+                        TypeOrConstParamData::ConstParamData(_) => None,
+                    })
+                    .collect::<Vec<_>>()
+            });
+        let generics = db.generic_params(self.def);
+        let type_params = generics.iter_type_or_consts().filter_map(|param| match param.1 {
+            TypeOrConstParamData::TypeParamData(param) => Some(param.name.clone()),
+            TypeOrConstParamData::ConstParamData(_) => None,
+        });
+        // The `Substitution` is first self then container, we want the reverse order.
+        let self_params = self.subst.type_parameters(Interner).zip(type_params);
+        let container_params = self.subst.as_slice(Interner)[generics.len()..]
+            .iter()
+            .filter_map(|param| param.ty(Interner).cloned())
+            .zip(container_type_params.into_iter().flatten());
+        container_params
+            .chain(self_params)
+            .filter_map(|(ty, name)| {
+                Some((name?.symbol().clone(), Type { ty, env: self.env.clone() }))
+            })
+            .collect()
+    }
+}
+
 /// A single local definition.
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 pub struct Local {
@@ -3902,6 +3957,22 @@ impl GenericParam {
             GenericParam::LifetimeParam(it) => it.id.parent.into(),
         }
     }
+
+    pub fn variance(self, db: &dyn HirDatabase) -> Option<Variance> {
+        let parent = match self {
+            GenericParam::TypeParam(it) => it.id.parent(),
+            // const parameters are always invariant
+            GenericParam::ConstParam(_) => return None,
+            GenericParam::LifetimeParam(it) => it.id.parent,
+        };
+        let generics = hir_ty::generics::generics(db.upcast(), parent);
+        let index = match self {
+            GenericParam::TypeParam(it) => generics.type_or_const_param_idx(it.id.into())?,
+            GenericParam::ConstParam(_) => return None,
+            GenericParam::LifetimeParam(it) => generics.lifetime_idx(it.id)?,
+        };
+        db.variances_of(parent)?.get(index).copied()
+    }
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
@@ -5152,21 +5223,18 @@ impl Type {
     ) -> Option<T> {
         let _p = tracing::info_span!("iterate_method_candidates_with_traits").entered();
         let mut slot = None;
-
-        self.iterate_method_candidates_dyn(
+        self.iterate_method_candidates_split_inherent(
             db,
             scope,
             traits_in_scope,
             with_local_impls,
             name,
-            &mut |assoc_item_id| {
-                if let AssocItemId::FunctionId(func) = assoc_item_id {
-                    if let Some(res) = callback(func.into()) {
-                        slot = Some(res);
-                        return ControlFlow::Break(());
-                    }
+            |f| match callback(f) {
+                it @ Some(_) => {
+                    slot = it;
+                    ControlFlow::Break(())
                 }
-                ControlFlow::Continue(())
+                None => ControlFlow::Continue(()),
             },
         );
         slot
@@ -5190,15 +5258,49 @@ impl Type {
         )
     }
 
-    fn iterate_method_candidates_dyn(
+    /// Allows you to treat inherent and non-inherent methods differently.
+    ///
+    /// Note that inherent methods may actually be trait methods! For example, in `dyn Trait`, the trait's methods
+    /// are considered inherent methods.
+    pub fn iterate_method_candidates_split_inherent(
         &self,
         db: &dyn HirDatabase,
         scope: &SemanticsScope<'_>,
         traits_in_scope: &FxHashSet<TraitId>,
         with_local_impls: Option<Module>,
         name: Option<&Name>,
-        callback: &mut dyn FnMut(AssocItemId) -> ControlFlow<()>,
+        callback: impl MethodCandidateCallback,
     ) {
+        struct Callback<T>(T);
+
+        impl<T: MethodCandidateCallback> method_resolution::MethodCandidateCallback for Callback<T> {
+            fn on_inherent_method(
+                &mut self,
+                _adjustments: method_resolution::ReceiverAdjustments,
+                item: AssocItemId,
+                _is_visible: bool,
+            ) -> ControlFlow<()> {
+                if let AssocItemId::FunctionId(func) = item {
+                    self.0.on_inherent_method(func.into())
+                } else {
+                    ControlFlow::Continue(())
+                }
+            }
+
+            fn on_trait_method(
+                &mut self,
+                _adjustments: method_resolution::ReceiverAdjustments,
+                item: AssocItemId,
+                _is_visible: bool,
+            ) -> ControlFlow<()> {
+                if let AssocItemId::FunctionId(func) = item {
+                    self.0.on_trait_method(func.into())
+                } else {
+                    ControlFlow::Continue(())
+                }
+            }
+        }
+
         let _p = tracing::info_span!(
             "iterate_method_candidates_dyn",
             with_local_impls = traits_in_scope.len(),
@@ -5223,7 +5325,7 @@ impl Type {
             with_local_impls.and_then(|b| b.id.containing_block()).into(),
             name,
             method_resolution::LookupMode::MethodCall,
-            &mut |_adj, id, _| callback(id),
+            &mut Callback(callback),
         );
     }
 
@@ -5239,33 +5341,61 @@ impl Type {
     ) -> Option<T> {
         let _p = tracing::info_span!("iterate_path_candidates").entered();
         let mut slot = None;
-        self.iterate_path_candidates_dyn(
+
+        self.iterate_path_candidates_split_inherent(
             db,
             scope,
             traits_in_scope,
             with_local_impls,
             name,
-            &mut |assoc_item_id| {
-                if let Some(res) = callback(assoc_item_id.into()) {
-                    slot = Some(res);
-                    return ControlFlow::Break(());
+            |item| match callback(item) {
+                it @ Some(_) => {
+                    slot = it;
+                    ControlFlow::Break(())
                 }
-                ControlFlow::Continue(())
+                None => ControlFlow::Continue(()),
             },
         );
         slot
     }
 
+    /// Iterates over inherent methods.
+    ///
+    /// In some circumstances, inherent methods methods may actually be trait methods!
+    /// For example, when `dyn Trait` is a receiver, _trait_'s methods would be considered
+    /// to be inherent methods.
     #[tracing::instrument(skip_all, fields(name = ?name))]
-    fn iterate_path_candidates_dyn(
+    pub fn iterate_path_candidates_split_inherent(
         &self,
         db: &dyn HirDatabase,
         scope: &SemanticsScope<'_>,
         traits_in_scope: &FxHashSet<TraitId>,
         with_local_impls: Option<Module>,
         name: Option<&Name>,
-        callback: &mut dyn FnMut(AssocItemId) -> ControlFlow<()>,
+        callback: impl PathCandidateCallback,
     ) {
+        struct Callback<T>(T);
+
+        impl<T: PathCandidateCallback> method_resolution::MethodCandidateCallback for Callback<T> {
+            fn on_inherent_method(
+                &mut self,
+                _adjustments: method_resolution::ReceiverAdjustments,
+                item: AssocItemId,
+                _is_visible: bool,
+            ) -> ControlFlow<()> {
+                self.0.on_inherent_item(item.into())
+            }
+
+            fn on_trait_method(
+                &mut self,
+                _adjustments: method_resolution::ReceiverAdjustments,
+                item: AssocItemId,
+                _is_visible: bool,
+            ) -> ControlFlow<()> {
+                self.0.on_trait_item(item.into())
+            }
+        }
+
         let canonical = hir_ty::replace_errors_with_variables(&self.ty);
 
         let krate = scope.krate();
@@ -5281,7 +5411,7 @@ impl Type {
             traits_in_scope,
             with_local_impls.and_then(|b| b.id.containing_block()).into(),
             name,
-            callback,
+            &mut Callback(callback),
         );
     }
 
@@ -5862,6 +5992,12 @@ impl HasCrate for Adt {
     }
 }
 
+impl HasCrate for Impl {
+    fn krate(&self, db: &dyn HirDatabase) -> Crate {
+        self.module(db).krate()
+    }
+}
+
 impl HasCrate for Module {
     fn krate(&self, _: &dyn HirDatabase) -> Crate {
         Module::krate(*self)
@@ -5983,3 +6119,41 @@ fn push_ty_diagnostics(
         );
     }
 }
+
+pub trait MethodCandidateCallback {
+    fn on_inherent_method(&mut self, f: Function) -> ControlFlow<()>;
+
+    fn on_trait_method(&mut self, f: Function) -> ControlFlow<()>;
+}
+
+impl<F> MethodCandidateCallback for F
+where
+    F: FnMut(Function) -> ControlFlow<()>,
+{
+    fn on_inherent_method(&mut self, f: Function) -> ControlFlow<()> {
+        self(f)
+    }
+
+    fn on_trait_method(&mut self, f: Function) -> ControlFlow<()> {
+        self(f)
+    }
+}
+
+pub trait PathCandidateCallback {
+    fn on_inherent_item(&mut self, item: AssocItem) -> ControlFlow<()>;
+
+    fn on_trait_item(&mut self, item: AssocItem) -> ControlFlow<()>;
+}
+
+impl<F> PathCandidateCallback for F
+where
+    F: FnMut(AssocItem) -> ControlFlow<()>,
+{
+    fn on_inherent_item(&mut self, item: AssocItem) -> ControlFlow<()> {
+        self(item)
+    }
+
+    fn on_trait_item(&mut self, item: AssocItem) -> ControlFlow<()> {
+        self(item)
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
index 1cf22b05e7f..34d169cd761 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
@@ -30,7 +30,7 @@ use hir_expand::{
     name::AsName,
     ExpandResult, FileRange, InMacroFile, MacroCallId, MacroFileId, MacroFileIdExt,
 };
-use intern::Symbol;
+use intern::{sym, Symbol};
 use itertools::Itertools;
 use rustc_hash::{FxHashMap, FxHashSet};
 use smallvec::{smallvec, SmallVec};
@@ -49,10 +49,10 @@ use crate::{
     semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
     source_analyzer::{name_hygiene, resolve_hir_path, SourceAnalyzer},
     Access, Adjust, Adjustment, Adt, AutoBorrow, BindingMode, BuiltinAttr, Callable, Const,
-    ConstParam, Crate, DeriveHelper, Enum, Field, Function, HasSource, HirFileId, Impl, InFile,
-    InlineAsmOperand, ItemInNs, Label, LifetimeParam, Local, Macro, Module, ModuleDef, Name,
-    OverloadedDeref, Path, ScopeDef, Static, Struct, ToolModule, Trait, TraitAlias, TupleField,
-    Type, TypeAlias, TypeParam, Union, Variant, VariantDef,
+    ConstParam, Crate, DeriveHelper, Enum, Field, Function, GenericSubstitution, HasSource,
+    HirFileId, Impl, InFile, InlineAsmOperand, ItemInNs, Label, LifetimeParam, Local, Macro,
+    Module, ModuleDef, Name, OverloadedDeref, Path, ScopeDef, Static, Struct, ToolModule, Trait,
+    TraitAlias, TupleField, Type, TypeAlias, TypeParam, Union, Variant, VariantDef,
 };
 
 const CONTINUE_NO_BREAKS: ControlFlow<Infallible, ()> = ControlFlow::Continue(());
@@ -246,59 +246,59 @@ impl<DB: HirDatabase> Semantics<'_, DB> {
     }
 
     pub fn to_adt_def(&self, a: &ast::Adt) -> Option<Adt> {
-        self.imp.to_def(a).map(Adt::from)
+        self.imp.to_def(a)
     }
 
     pub fn to_const_def(&self, c: &ast::Const) -> Option<Const> {
-        self.imp.to_def(c).map(Const::from)
+        self.imp.to_def(c)
     }
 
     pub fn to_enum_def(&self, e: &ast::Enum) -> Option<Enum> {
-        self.imp.to_def(e).map(Enum::from)
+        self.imp.to_def(e)
     }
 
     pub fn to_enum_variant_def(&self, v: &ast::Variant) -> Option<Variant> {
-        self.imp.to_def(v).map(Variant::from)
+        self.imp.to_def(v)
     }
 
     pub fn to_fn_def(&self, f: &ast::Fn) -> Option<Function> {
-        self.imp.to_def(f).map(Function::from)
+        self.imp.to_def(f)
     }
 
     pub fn to_impl_def(&self, i: &ast::Impl) -> Option<Impl> {
-        self.imp.to_def(i).map(Impl::from)
+        self.imp.to_def(i)
     }
 
     pub fn to_macro_def(&self, m: &ast::Macro) -> Option<Macro> {
-        self.imp.to_def(m).map(Macro::from)
+        self.imp.to_def(m)
     }
 
     pub fn to_module_def(&self, m: &ast::Module) -> Option<Module> {
-        self.imp.to_def(m).map(Module::from)
+        self.imp.to_def(m)
     }
 
     pub fn to_static_def(&self, s: &ast::Static) -> Option<Static> {
-        self.imp.to_def(s).map(Static::from)
+        self.imp.to_def(s)
     }
 
     pub fn to_struct_def(&self, s: &ast::Struct) -> Option<Struct> {
-        self.imp.to_def(s).map(Struct::from)
+        self.imp.to_def(s)
     }
 
     pub fn to_trait_alias_def(&self, t: &ast::TraitAlias) -> Option<TraitAlias> {
-        self.imp.to_def(t).map(TraitAlias::from)
+        self.imp.to_def(t)
     }
 
     pub fn to_trait_def(&self, t: &ast::Trait) -> Option<Trait> {
-        self.imp.to_def(t).map(Trait::from)
+        self.imp.to_def(t)
     }
 
     pub fn to_type_alias_def(&self, t: &ast::TypeAlias) -> Option<TypeAlias> {
-        self.imp.to_def(t).map(TypeAlias::from)
+        self.imp.to_def(t)
     }
 
     pub fn to_union_def(&self, u: &ast::Union) -> Option<Union> {
-        self.imp.to_def(u).map(Union::from)
+        self.imp.to_def(u)
     }
 }
 
@@ -811,10 +811,37 @@ impl<'db> SemanticsImpl<'db> {
             item.attrs().any(|attr| {
                 let Some(meta) = attr.meta() else { return false };
                 let Some(path) = meta.path() else { return false };
-                let Some(attr_name) = path.as_single_name_ref() else { return true };
-                let attr_name = attr_name.text();
-                let attr_name = attr_name.as_str();
-                attr_name == "derive" || find_builtin_attr_idx(&Symbol::intern(attr_name)).is_none()
+                if let Some(attr_name) = path.as_single_name_ref() {
+                    let attr_name = attr_name.text();
+                    let attr_name = Symbol::intern(attr_name.as_str());
+                    if attr_name == sym::derive {
+                        return true;
+                    }
+                    // We ignore `#[test]` and friends in the def map, so we cannot expand them.
+                    // FIXME: We match by text. This is both hacky and incorrect (people can, and do, create
+                    // other macros named `test`). We cannot fix that unfortunately because we use this method
+                    // for speculative expansion in completion, which we cannot analyze. Fortunately, most macros
+                    // named `test` are test-like, meaning their expansion is not terribly important for IDE.
+                    if attr_name == sym::test
+                        || attr_name == sym::bench
+                        || attr_name == sym::test_case
+                        || find_builtin_attr_idx(&attr_name).is_some()
+                    {
+                        return false;
+                    }
+                }
+                let mut segments = path.segments();
+                let mut next_segment_text = || segments.next().and_then(|it| it.name_ref());
+                // `#[core::prelude::rust_2024::test]` or `#[std::prelude::rust_2024::test]`.
+                if next_segment_text().is_some_and(|it| matches!(&*it.text(), "core" | "std"))
+                    && next_segment_text().is_some_and(|it| it.text() == "prelude")
+                    && next_segment_text().is_some()
+                    && next_segment_text()
+                        .is_some_and(|it| matches!(&*it.text(), "test" | "bench" | "test_case"))
+                {
+                    return false;
+                }
+                true
             })
         })
     }
@@ -1206,7 +1233,6 @@ impl<'db> SemanticsImpl<'db> {
         node.original_file_range_opt(self.db.upcast())
             .filter(|(_, ctx)| ctx.is_root())
             .map(TupleExt::head)
-            .map(Into::into)
     }
 
     /// Attempts to map the node out of macro expanded files.
@@ -1413,7 +1439,7 @@ impl<'db> SemanticsImpl<'db> {
     pub fn resolve_method_call_fallback(
         &self,
         call: &ast::MethodCallExpr,
-    ) -> Option<Either<Function, Field>> {
+    ) -> Option<(Either<Function, Field>, Option<GenericSubstitution>)> {
         self.analyze(call.syntax())?.resolve_method_call_fallback(self.db, call)
     }
 
@@ -1456,7 +1482,7 @@ impl<'db> SemanticsImpl<'db> {
     pub fn resolve_field_fallback(
         &self,
         field: &ast::FieldExpr,
-    ) -> Option<Either<Either<Field, TupleField>, Function>> {
+    ) -> Option<(Either<Either<Field, TupleField>, Function>, Option<GenericSubstitution>)> {
         self.analyze(field.syntax())?.resolve_field_fallback(self.db, field)
     }
 
@@ -1464,10 +1490,25 @@ impl<'db> SemanticsImpl<'db> {
         &self,
         field: &ast::RecordExprField,
     ) -> Option<(Field, Option<Local>, Type)> {
+        self.resolve_record_field_with_substitution(field)
+            .map(|(field, local, ty, _)| (field, local, ty))
+    }
+
+    pub fn resolve_record_field_with_substitution(
+        &self,
+        field: &ast::RecordExprField,
+    ) -> Option<(Field, Option<Local>, Type, GenericSubstitution)> {
         self.analyze(field.syntax())?.resolve_record_field(self.db, field)
     }
 
     pub fn resolve_record_pat_field(&self, field: &ast::RecordPatField) -> Option<(Field, Type)> {
+        self.resolve_record_pat_field_with_subst(field).map(|(field, ty, _)| (field, ty))
+    }
+
+    pub fn resolve_record_pat_field_with_subst(
+        &self,
+        field: &ast::RecordPatField,
+    ) -> Option<(Field, Type, GenericSubstitution)> {
         self.analyze(field.syntax())?.resolve_record_pat_field(self.db, field)
     }
 
@@ -1485,7 +1526,7 @@ impl<'db> SemanticsImpl<'db> {
 
     pub fn is_proc_macro_call(&self, macro_call: &ast::MacroCall) -> bool {
         self.resolve_macro_call(macro_call)
-            .map_or(false, |m| matches!(m.id, MacroId::ProcMacroId(..)))
+            .is_some_and(|m| matches!(m.id, MacroId::ProcMacroId(..)))
     }
 
     pub fn resolve_macro_call_arm(&self, macro_call: &ast::MacroCall) -> Option<u32> {
@@ -1523,6 +1564,13 @@ impl<'db> SemanticsImpl<'db> {
     }
 
     pub fn resolve_path(&self, path: &ast::Path) -> Option<PathResolution> {
+        self.resolve_path_with_subst(path).map(|(it, _)| it)
+    }
+
+    pub fn resolve_path_with_subst(
+        &self,
+        path: &ast::Path,
+    ) -> Option<(PathResolution, Option<GenericSubstitution>)> {
         self.analyze(path.syntax())?.resolve_path(self.db, path)
     }
 
@@ -2038,6 +2086,11 @@ impl SemanticsScope<'_> {
         )
     }
 
+    pub fn resolve_mod_path(&self, path: &ModPath) -> impl Iterator<Item = ItemInNs> {
+        let items = self.resolver.resolve_module_path_in_items(self.db.upcast(), path);
+        items.iter_items().map(|(item, _)| item.into())
+    }
+
     /// Iterates over associated types that may be specified after the given path (using
     /// `Ty::Assoc` syntax).
     pub fn assoc_type_shorthand_candidates<R>(
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
index 08333c2d76c..b5cc440fc22 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
@@ -408,7 +408,7 @@ impl SourceToDefCtx<'_, '_> {
     }
 
     pub(super) fn has_derives(&mut self, adt: InFile<&ast::Adt>) -> bool {
-        self.dyn_map(adt).as_ref().map_or(false, |map| !map[keys::DERIVE_MACRO_CALL].is_empty())
+        self.dyn_map(adt).as_ref().is_some_and(|map| !map[keys::DERIVE_MACRO_CALL].is_empty())
     }
 
     fn to_def<Ast: AstNode + 'static, ID: Copy + 'static>(
diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
index 4329a888b39..b699ccde412 100644
--- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
@@ -9,8 +9,8 @@ use std::iter::{self, once};
 
 use crate::{
     db::HirDatabase, semantics::PathResolution, Adt, AssocItem, BindingMode, BuiltinAttr,
-    BuiltinType, Callable, Const, DeriveHelper, Field, Function, Local, Macro, ModuleDef, Static,
-    Struct, ToolModule, Trait, TraitAlias, TupleField, Type, TypeAlias, Variant,
+    BuiltinType, Callable, Const, DeriveHelper, Field, Function, GenericSubstitution, Local, Macro,
+    ModuleDef, Static, Struct, ToolModule, Trait, TraitAlias, TupleField, Type, TypeAlias, Variant,
 };
 use either::Either;
 use hir_def::{
@@ -18,15 +18,15 @@ use hir_def::{
         scope::{ExprScopes, ScopeId},
         Body, BodySourceMap, HygieneId,
     },
-    hir::{BindingId, ExprId, ExprOrPatId, Pat, PatId},
+    hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat, PatId},
     lang_item::LangItem,
     lower::LowerCtx,
     nameres::MacroSubNs,
     path::{ModPath, Path, PathKind},
     resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs},
     type_ref::{Mutability, TypesMap, TypesSourceMap},
-    AsMacroCall, AssocItemId, ConstId, DefWithBodyId, FieldId, FunctionId, ItemContainerId,
-    LocalFieldId, Lookup, ModuleDefId, StructId, TraitId, VariantId,
+    AsMacroCall, AssocItemId, CallableDefId, ConstId, DefWithBodyId, FieldId, FunctionId,
+    ItemContainerId, LocalFieldId, Lookup, ModuleDefId, StructId, TraitId, VariantId,
 };
 use hir_expand::{
     mod_path::path,
@@ -38,9 +38,10 @@ use hir_ty::{
         record_literal_missing_fields, record_pattern_missing_fields, unsafe_expressions,
         InsideUnsafeBlock,
     },
+    from_assoc_type_id,
     lang_items::lang_items_for_bin_op,
-    method_resolution, Adjustment, InferenceResult, Interner, Substitution, Ty, TyExt, TyKind,
-    TyLoweringContext,
+    method_resolution, Adjustment, InferenceResult, Interner, Substitution, TraitEnvironment, Ty,
+    TyExt, TyKind, TyLoweringContext,
 };
 use intern::sym;
 use itertools::Itertools;
@@ -120,6 +121,13 @@ impl SourceAnalyzer {
         self.def.as_ref().map(|(_, body, _)| &**body)
     }
 
+    fn trait_environment(&self, db: &dyn HirDatabase) -> Arc<TraitEnvironment> {
+        self.def.as_ref().map(|(def, ..)| *def).map_or_else(
+            || TraitEnvironment::empty(self.resolver.krate()),
+            |def| db.trait_environment_for_body(def),
+        )
+    }
+
     fn expr_id(&self, db: &dyn HirDatabase, expr: &ast::Expr) -> Option<ExprOrPatId> {
         let src = match expr {
             ast::Expr::MacroExpr(expr) => {
@@ -294,18 +302,23 @@ impl SourceAnalyzer {
         &self,
         db: &dyn HirDatabase,
         call: &ast::MethodCallExpr,
-    ) -> Option<Either<Function, Field>> {
+    ) -> Option<(Either<Function, Field>, Option<GenericSubstitution>)> {
         let expr_id = self.expr_id(db, &call.clone().into())?.as_expr()?;
         let inference_result = self.infer.as_ref()?;
         match inference_result.method_resolution(expr_id) {
-            Some((f_in_trait, substs)) => Some(Either::Left(
-                self.resolve_impl_method_or_trait_def(db, f_in_trait, substs).into(),
-            )),
-            None => inference_result
-                .field_resolution(expr_id)
-                .and_then(Either::left)
-                .map(Into::into)
-                .map(Either::Right),
+            Some((f_in_trait, substs)) => {
+                let (fn_, subst) =
+                    self.resolve_impl_method_or_trait_def_with_subst(db, f_in_trait, substs);
+                Some((
+                    Either::Left(fn_.into()),
+                    Some(GenericSubstitution::new(fn_.into(), subst, self.trait_environment(db))),
+                ))
+            }
+            None => {
+                inference_result.field_resolution(expr_id).and_then(Either::left).map(|field| {
+                    (Either::Right(field.into()), self.field_subst(expr_id, inference_result, db))
+                })
+            }
         }
     }
 
@@ -330,22 +343,53 @@ impl SourceAnalyzer {
         })
     }
 
+    fn field_subst(
+        &self,
+        field_expr: ExprId,
+        infer: &InferenceResult,
+        db: &dyn HirDatabase,
+    ) -> Option<GenericSubstitution> {
+        let body = self.body()?;
+        if let Expr::Field { expr: object_expr, name: _ } = body[field_expr] {
+            let (adt, subst) = type_of_expr_including_adjust(infer, object_expr)?.as_adt()?;
+            return Some(GenericSubstitution::new(
+                adt.into(),
+                subst.clone(),
+                self.trait_environment(db),
+            ));
+        }
+        None
+    }
+
     pub(crate) fn resolve_field_fallback(
         &self,
         db: &dyn HirDatabase,
         field: &ast::FieldExpr,
-    ) -> Option<Either<Either<Field, TupleField>, Function>> {
+    ) -> Option<(Either<Either<Field, TupleField>, Function>, Option<GenericSubstitution>)> {
         let &(def, ..) = self.def.as_ref()?;
         let expr_id = self.expr_id(db, &field.clone().into())?.as_expr()?;
         let inference_result = self.infer.as_ref()?;
         match inference_result.field_resolution(expr_id) {
-            Some(field) => Some(Either::Left(field.map_either(Into::into, |f| TupleField {
-                owner: def,
-                tuple: f.tuple,
-                index: f.index,
-            }))),
+            Some(field) => match field {
+                Either::Left(field) => Some((
+                    Either::Left(Either::Left(field.into())),
+                    self.field_subst(expr_id, inference_result, db),
+                )),
+                Either::Right(field) => Some((
+                    Either::Left(Either::Right(TupleField {
+                        owner: def,
+                        tuple: field.tuple,
+                        index: field.index,
+                    })),
+                    None,
+                )),
+            },
             None => inference_result.method_resolution(expr_id).map(|(f, substs)| {
-                Either::Right(self.resolve_impl_method_or_trait_def(db, f, substs).into())
+                let (f, subst) = self.resolve_impl_method_or_trait_def_with_subst(db, f, substs);
+                (
+                    Either::Right(f.into()),
+                    Some(GenericSubstitution::new(f.into(), subst, self.trait_environment(db))),
+                )
             }),
         }
     }
@@ -557,7 +601,7 @@ impl SourceAnalyzer {
         &self,
         db: &dyn HirDatabase,
         field: &ast::RecordExprField,
-    ) -> Option<(Field, Option<Local>, Type)> {
+    ) -> Option<(Field, Option<Local>, Type, GenericSubstitution)> {
         let record_expr = ast::RecordExpr::cast(field.syntax().parent().and_then(|p| p.parent())?)?;
         let expr = ast::Expr::from(record_expr);
         let expr_id = self.body_source_map()?.node_expr(InFile::new(self.file_id, &expr))?;
@@ -583,30 +627,39 @@ impl SourceAnalyzer {
                 _ => None,
             }
         };
-        let (_, subst) = self.infer.as_ref()?.type_of_expr_or_pat(expr_id)?.as_adt()?;
+        let (adt, subst) = self.infer.as_ref()?.type_of_expr_or_pat(expr_id)?.as_adt()?;
         let variant = self.infer.as_ref()?.variant_resolution_for_expr_or_pat(expr_id)?;
         let variant_data = variant.variant_data(db.upcast());
         let field = FieldId { parent: variant, local_id: variant_data.field(&local_name)? };
         let field_ty =
             db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, subst);
-        Some((field.into(), local, Type::new_with_resolver(db, &self.resolver, field_ty)))
+        Some((
+            field.into(),
+            local,
+            Type::new_with_resolver(db, &self.resolver, field_ty),
+            GenericSubstitution::new(adt.into(), subst.clone(), self.trait_environment(db)),
+        ))
     }
 
     pub(crate) fn resolve_record_pat_field(
         &self,
         db: &dyn HirDatabase,
         field: &ast::RecordPatField,
-    ) -> Option<(Field, Type)> {
+    ) -> Option<(Field, Type, GenericSubstitution)> {
         let field_name = field.field_name()?.as_name();
         let record_pat = ast::RecordPat::cast(field.syntax().parent().and_then(|p| p.parent())?)?;
         let pat_id = self.pat_id(&record_pat.into())?;
         let variant = self.infer.as_ref()?.variant_resolution_for_pat(pat_id)?;
         let variant_data = variant.variant_data(db.upcast());
         let field = FieldId { parent: variant, local_id: variant_data.field(&field_name)? };
-        let (_, subst) = self.infer.as_ref()?.type_of_pat.get(pat_id)?.as_adt()?;
+        let (adt, subst) = self.infer.as_ref()?.type_of_pat.get(pat_id)?.as_adt()?;
         let field_ty =
             db.field_types(variant).get(field.local_id)?.clone().substitute(Interner, subst);
-        Some((field.into(), Type::new_with_resolver(db, &self.resolver, field_ty)))
+        Some((
+            field.into(),
+            Type::new_with_resolver(db, &self.resolver, field_ty),
+            GenericSubstitution::new(adt.into(), subst.clone(), self.trait_environment(db)),
+        ))
     }
 
     pub(crate) fn resolve_macro_call(
@@ -654,7 +707,7 @@ impl SourceAnalyzer {
         &self,
         db: &dyn HirDatabase,
         path: &ast::Path,
-    ) -> Option<PathResolution> {
+    ) -> Option<(PathResolution, Option<GenericSubstitution>)> {
         let parent = path.syntax().parent();
         let parent = || parent.clone();
 
@@ -664,60 +717,106 @@ impl SourceAnalyzer {
             if let Some(path_expr) = parent().and_then(ast::PathExpr::cast) {
                 let expr_id = self.expr_id(db, &path_expr.into())?;
                 if let Some((assoc, subs)) = infer.assoc_resolutions_for_expr_or_pat(expr_id) {
-                    let assoc = match assoc {
+                    let (assoc, subst) = match assoc {
                         AssocItemId::FunctionId(f_in_trait) => {
                             match infer.type_of_expr_or_pat(expr_id) {
-                                None => assoc,
+                                None => {
+                                    let subst = GenericSubstitution::new(
+                                        f_in_trait.into(),
+                                        subs,
+                                        self.trait_environment(db),
+                                    );
+                                    (assoc, subst)
+                                }
                                 Some(func_ty) => {
                                     if let TyKind::FnDef(_fn_def, subs) = func_ty.kind(Interner) {
-                                        self.resolve_impl_method_or_trait_def(
-                                            db,
-                                            f_in_trait,
-                                            subs.clone(),
-                                        )
-                                        .into()
+                                        let (fn_, subst) = self
+                                            .resolve_impl_method_or_trait_def_with_subst(
+                                                db,
+                                                f_in_trait,
+                                                subs.clone(),
+                                            );
+                                        let subst = GenericSubstitution::new(
+                                            fn_.into(),
+                                            subst,
+                                            self.trait_environment(db),
+                                        );
+                                        (fn_.into(), subst)
                                     } else {
-                                        assoc
+                                        let subst = GenericSubstitution::new(
+                                            f_in_trait.into(),
+                                            subs,
+                                            self.trait_environment(db),
+                                        );
+                                        (assoc, subst)
                                     }
                                 }
                             }
                         }
                         AssocItemId::ConstId(const_id) => {
-                            self.resolve_impl_const_or_trait_def(db, const_id, subs).into()
+                            let (konst, subst) =
+                                self.resolve_impl_const_or_trait_def_with_subst(db, const_id, subs);
+                            let subst = GenericSubstitution::new(
+                                konst.into(),
+                                subst,
+                                self.trait_environment(db),
+                            );
+                            (konst.into(), subst)
                         }
-                        assoc => assoc,
+                        AssocItemId::TypeAliasId(type_alias) => (
+                            assoc,
+                            GenericSubstitution::new(
+                                type_alias.into(),
+                                subs,
+                                self.trait_environment(db),
+                            ),
+                        ),
                     };
 
-                    return Some(PathResolution::Def(AssocItem::from(assoc).into()));
+                    return Some((PathResolution::Def(AssocItem::from(assoc).into()), Some(subst)));
                 }
                 if let Some(VariantId::EnumVariantId(variant)) =
                     infer.variant_resolution_for_expr_or_pat(expr_id)
                 {
-                    return Some(PathResolution::Def(ModuleDef::Variant(variant.into())));
+                    return Some((PathResolution::Def(ModuleDef::Variant(variant.into())), None));
                 }
                 prefer_value_ns = true;
             } else if let Some(path_pat) = parent().and_then(ast::PathPat::cast) {
                 let pat_id = self.pat_id(&path_pat.into())?;
                 if let Some((assoc, subs)) = infer.assoc_resolutions_for_pat(pat_id) {
-                    let assoc = match assoc {
+                    let (assoc, subst) = match assoc {
                         AssocItemId::ConstId(const_id) => {
-                            self.resolve_impl_const_or_trait_def(db, const_id, subs).into()
+                            let (konst, subst) =
+                                self.resolve_impl_const_or_trait_def_with_subst(db, const_id, subs);
+                            let subst = GenericSubstitution::new(
+                                konst.into(),
+                                subst,
+                                self.trait_environment(db),
+                            );
+                            (konst.into(), subst)
                         }
-                        assoc => assoc,
+                        assoc => (
+                            assoc,
+                            GenericSubstitution::new(
+                                assoc.into(),
+                                subs,
+                                self.trait_environment(db),
+                            ),
+                        ),
                     };
-                    return Some(PathResolution::Def(AssocItem::from(assoc).into()));
+                    return Some((PathResolution::Def(AssocItem::from(assoc).into()), Some(subst)));
                 }
                 if let Some(VariantId::EnumVariantId(variant)) =
                     infer.variant_resolution_for_pat(pat_id)
                 {
-                    return Some(PathResolution::Def(ModuleDef::Variant(variant.into())));
+                    return Some((PathResolution::Def(ModuleDef::Variant(variant.into())), None));
                 }
             } else if let Some(rec_lit) = parent().and_then(ast::RecordExpr::cast) {
                 let expr_id = self.expr_id(db, &rec_lit.into())?;
                 if let Some(VariantId::EnumVariantId(variant)) =
                     infer.variant_resolution_for_expr_or_pat(expr_id)
                 {
-                    return Some(PathResolution::Def(ModuleDef::Variant(variant.into())));
+                    return Some((PathResolution::Def(ModuleDef::Variant(variant.into())), None));
                 }
             } else {
                 let record_pat = parent().and_then(ast::RecordPat::cast).map(ast::Pat::from);
@@ -727,7 +826,10 @@ impl SourceAnalyzer {
                     let pat_id = self.pat_id(&pat)?;
                     let variant_res_for_pat = infer.variant_resolution_for_pat(pat_id);
                     if let Some(VariantId::EnumVariantId(variant)) = variant_res_for_pat {
-                        return Some(PathResolution::Def(ModuleDef::Variant(variant.into())));
+                        return Some((
+                            PathResolution::Def(ModuleDef::Variant(variant.into())),
+                            None,
+                        ));
                     }
                 }
             }
@@ -747,7 +849,8 @@ impl SourceAnalyzer {
         // trying to resolve foo::bar.
         if let Some(use_tree) = parent().and_then(ast::UseTree::cast) {
             if use_tree.coloncolon_token().is_some() {
-                return resolve_hir_path_qualifier(db, &self.resolver, &hir_path, &types_map);
+                return resolve_hir_path_qualifier(db, &self.resolver, &hir_path, &types_map)
+                    .map(|it| (it, None));
             }
         }
 
@@ -765,13 +868,18 @@ impl SourceAnalyzer {
         // trying to resolve foo::bar.
         if path.parent_path().is_some() {
             return match resolve_hir_path_qualifier(db, &self.resolver, &hir_path, &types_map) {
-                None if meta_path.is_some() => {
-                    path.first_segment().and_then(|it| it.name_ref()).and_then(|name_ref| {
+                None if meta_path.is_some() => path
+                    .first_segment()
+                    .and_then(|it| it.name_ref())
+                    .and_then(|name_ref| {
                         ToolModule::by_name(db, self.resolver.krate().into(), &name_ref.text())
                             .map(PathResolution::ToolModule)
                     })
-                }
-                res => res,
+                    .map(|it| (it, None)),
+                // FIXME: We do not show substitutions for parts of path, because this is really complex
+                // due to the interactions with associated items of `impl`s and associated items of associated
+                // types.
+                res => res.map(|it| (it, None)),
             };
         } else if let Some(meta_path) = meta_path {
             // Case where we are resolving the final path segment of a path in an attribute
@@ -781,7 +889,7 @@ impl SourceAnalyzer {
                 let builtin =
                     BuiltinAttr::by_name(db, self.resolver.krate().into(), &name_ref.text());
                 if builtin.is_some() {
-                    return builtin.map(PathResolution::BuiltinAttr);
+                    return builtin.map(|it| (PathResolution::BuiltinAttr(it), None));
                 }
 
                 if let Some(attr) = meta_path.parent_attr() {
@@ -814,10 +922,13 @@ impl SourceAnalyzer {
                             {
                                 if let Some(idx) = helpers.position(|(name, ..)| *name == name_ref)
                                 {
-                                    return Some(PathResolution::DeriveHelper(DeriveHelper {
-                                        derive: *macro_id,
-                                        idx: idx as u32,
-                                    }));
+                                    return Some((
+                                        PathResolution::DeriveHelper(DeriveHelper {
+                                            derive: *macro_id,
+                                            idx: idx as u32,
+                                        }),
+                                        None,
+                                    ));
                                 }
                             }
                         }
@@ -825,26 +936,79 @@ impl SourceAnalyzer {
                 }
             }
             return match resolve_hir_path_as_attr_macro(db, &self.resolver, &hir_path) {
-                Some(m) => Some(PathResolution::Def(ModuleDef::Macro(m))),
+                Some(m) => Some((PathResolution::Def(ModuleDef::Macro(m)), None)),
                 // this labels any path that starts with a tool module as the tool itself, this is technically wrong
                 // but there is no benefit in differentiating these two cases for the time being
-                None => path.first_segment().and_then(|it| it.name_ref()).and_then(|name_ref| {
-                    ToolModule::by_name(db, self.resolver.krate().into(), &name_ref.text())
-                        .map(PathResolution::ToolModule)
-                }),
+                None => path
+                    .first_segment()
+                    .and_then(|it| it.name_ref())
+                    .and_then(|name_ref| {
+                        ToolModule::by_name(db, self.resolver.krate().into(), &name_ref.text())
+                            .map(PathResolution::ToolModule)
+                    })
+                    .map(|it| (it, None)),
             };
         }
-        if parent().map_or(false, |it| ast::Visibility::can_cast(it.kind())) {
+        if parent().is_some_and(|it| ast::Visibility::can_cast(it.kind())) {
+            // No substitution because only modules can be inside visibilities, and those have no generics.
             resolve_hir_path_qualifier(db, &self.resolver, &hir_path, &types_map)
+                .map(|it| (it, None))
         } else {
-            resolve_hir_path_(
+            // Probably a type, no need to show substitutions for those.
+            let res = resolve_hir_path_(
                 db,
                 &self.resolver,
                 &hir_path,
                 prefer_value_ns,
                 name_hygiene(db, InFile::new(self.file_id, path.syntax())),
                 &types_map,
-            )
+            )?;
+            let subst = (|| {
+                let parent = parent()?;
+                let ty = if let Some(expr) = ast::Expr::cast(parent.clone()) {
+                    let expr_id = self.expr_id(db, &expr)?;
+                    self.infer.as_ref()?.type_of_expr_or_pat(expr_id)?
+                } else if let Some(pat) = ast::Pat::cast(parent) {
+                    let pat_id = self.pat_id(&pat)?;
+                    &self.infer.as_ref()?[pat_id]
+                } else {
+                    return None;
+                };
+                let env = self.trait_environment(db);
+                let (subst, expected_resolution) = match ty.kind(Interner) {
+                    TyKind::Adt(adt_id, subst) => (
+                        GenericSubstitution::new(adt_id.0.into(), subst.clone(), env),
+                        PathResolution::Def(ModuleDef::Adt(adt_id.0.into())),
+                    ),
+                    TyKind::AssociatedType(assoc_id, subst) => {
+                        let assoc_id = from_assoc_type_id(*assoc_id);
+                        (
+                            GenericSubstitution::new(assoc_id.into(), subst.clone(), env),
+                            PathResolution::Def(ModuleDef::TypeAlias(assoc_id.into())),
+                        )
+                    }
+                    TyKind::FnDef(fn_id, subst) => {
+                        let fn_id = hir_ty::db::InternedCallableDefId::from(*fn_id);
+                        let fn_id = db.lookup_intern_callable_def(fn_id);
+                        let generic_def_id = match fn_id {
+                            CallableDefId::StructId(id) => id.into(),
+                            CallableDefId::FunctionId(id) => id.into(),
+                            CallableDefId::EnumVariantId(_) => return None,
+                        };
+                        (
+                            GenericSubstitution::new(generic_def_id, subst.clone(), env),
+                            PathResolution::Def(ModuleDefId::from(fn_id).into()),
+                        )
+                    }
+                    _ => return None,
+                };
+                if res != expected_resolution {
+                    // The user will not understand where we're coming from. This can happen (I think) with type aliases.
+                    return None;
+                }
+                Some(subst)
+            })();
+            Some((res, subst))
         }
     }
 
@@ -1041,26 +1205,35 @@ impl SourceAnalyzer {
         func: FunctionId,
         substs: Substitution,
     ) -> FunctionId {
+        self.resolve_impl_method_or_trait_def_with_subst(db, func, substs).0
+    }
+
+    fn resolve_impl_method_or_trait_def_with_subst(
+        &self,
+        db: &dyn HirDatabase,
+        func: FunctionId,
+        substs: Substitution,
+    ) -> (FunctionId, Substitution) {
         let owner = match self.resolver.body_owner() {
             Some(it) => it,
-            None => return func,
+            None => return (func, substs),
         };
         let env = db.trait_environment_for_body(owner);
-        db.lookup_impl_method(env, func, substs).0
+        db.lookup_impl_method(env, func, substs)
     }
 
-    fn resolve_impl_const_or_trait_def(
+    fn resolve_impl_const_or_trait_def_with_subst(
         &self,
         db: &dyn HirDatabase,
         const_id: ConstId,
         subs: Substitution,
-    ) -> ConstId {
+    ) -> (ConstId, Substitution) {
         let owner = match self.resolver.body_owner() {
             Some(it) => it,
-            None => return const_id,
+            None => return (const_id, subs),
         };
         let env = db.trait_environment_for_body(owner);
-        method_resolution::lookup_impl_const(db, env, const_id, subs).0
+        method_resolution::lookup_impl_const(db, env, const_id, subs)
     }
 
     fn lang_trait_fn(
@@ -1413,3 +1586,10 @@ pub(crate) fn name_hygiene(db: &dyn HirDatabase, name: InFile<&SyntaxNode>) -> H
     let ctx = db.lookup_intern_syntax_context(ctx);
     HygieneId::new(ctx.opaque_and_semitransparent)
 }
+
+fn type_of_expr_including_adjust(infer: &InferenceResult, id: ExprId) -> Option<&Ty> {
+    match infer.expr_adjustments.get(&id).and_then(|adjustments| adjustments.last()) {
+        Some(adjustment) => Some(&adjustment.target),
+        None => infer.type_of_expr.get(id),
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_lifetime_to_type.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_lifetime_to_type.rs
index 12213c8455c..43c0a72fa47 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_lifetime_to_type.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_lifetime_to_type.rs
@@ -28,7 +28,7 @@ pub(crate) fn add_lifetime_to_type(acc: &mut Assists, ctx: &AssistContext<'_>) -
     let node = ctx.find_node_at_offset::<ast::Adt>()?;
     let has_lifetime = node
         .generic_param_list()
-        .map_or(false, |gen_list| gen_list.lifetime_params().next().is_some());
+        .is_some_and(|gen_list| gen_list.lifetime_params().next().is_some());
 
     if has_lifetime {
         return None;
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs
index 236d33878ed..24b34f140bd 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs
@@ -220,7 +220,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
                 .arms()
                 .find(|arm| matches!(arm.pat(), Some(ast::Pat::WildcardPat(_))));
             if let Some(arm) = catch_all_arm {
-                let is_empty_expr = arm.expr().map_or(true, |e| match e {
+                let is_empty_expr = arm.expr().is_none_or(|e| match e {
                     ast::Expr::BlockExpr(b) => {
                         b.statements().next().is_none() && b.tail_expr().is_none()
                     }
@@ -261,7 +261,9 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
             }
 
             if let Some(cap) = ctx.config.snippet_cap {
-                if let Some(it) = first_new_arm.and_then(|arm| arm.syntax().descendants().find_map(ast::WildcardPat::cast)) {
+                if let Some(it) = first_new_arm
+                    .and_then(|arm| arm.syntax().descendants().find_map(ast::WildcardPat::cast))
+                {
                     edit.add_placeholder_snippet(cap, it);
                 }
 
@@ -287,14 +289,10 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
                         syntax::SyntaxElement::from(edit.make_syntax_mut(it))
                     }
                     syntax::SyntaxElement::Token(it) => {
-                        // Don't have a way to make tokens mut, so instead make the parent mut
-                        // and find the token again
-                        let parent =
-                            edit.make_syntax_mut(it.parent().expect("Token must have a parent."));
-                        let mut_token =
-                            parent.covering_element(it.text_range()).into_token().expect("Covering element cannot be found. Range may be beyond the current node's range");
-
-                        syntax::SyntaxElement::from(mut_token)
+                        // If a token is found, it is '{' or '}'
+                        // The parent is `{ ... }`
+                        let parent = it.parent().expect("Token must have a parent.");
+                        syntax::SyntaxElement::from(edit.make_syntax_mut(parent))
                     }
                 }
             };
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs
index 0f6970d9403..62700ab1809 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_turbo_fish.rs
@@ -69,7 +69,7 @@ pub(crate) fn add_turbo_fish(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
     let ident = name_ref.ident_token()?;
 
     let def = match NameRefClass::classify(&ctx.sema, &name_ref)? {
-        NameRefClass::Definition(def) => def,
+        NameRefClass::Definition(def, _) => def,
         NameRefClass::FieldShorthand { .. } | NameRefClass::ExternCrateShorthand { .. } => {
             return None
         }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_match_to_let_else.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_match_to_let_else.rs
index c7f41ffce04..fd159eb824d 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_match_to_let_else.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_match_to_let_else.rs
@@ -103,7 +103,7 @@ fn find_extracted_variable(ctx: &AssistContext<'_>, arm: &ast::MatchArm) -> Opti
         ast::Expr::PathExpr(path) => {
             let name_ref = path.syntax().descendants().find_map(ast::NameRef::cast)?;
             match NameRefClass::classify(&ctx.sema, &name_ref)? {
-                NameRefClass::Definition(Definition::Local(local)) => {
+                NameRefClass::Definition(Definition::Local(local), _) => {
                     let source =
                         local.sources(ctx.db()).into_iter().map(|x| x.into_ident_pat()?.name());
                     source.collect()
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_nested_function_to_closure.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_nested_function_to_closure.rs
index c30f3e1c3b2..ea2752b8818 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_nested_function_to_closure.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_nested_function_to_closure.rs
@@ -63,7 +63,7 @@ pub(crate) fn convert_nested_function_to_closure(
 
 /// Returns whether the given function is nested within the body of another function.
 fn is_nested_function(function: &ast::Fn) -> bool {
-    function.syntax().ancestors().skip(1).find_map(ast::Item::cast).map_or(false, |it| {
+    function.syntax().ancestors().skip(1).find_map(ast::Item::cast).is_some_and(|it| {
         matches!(it, ast::Item::Fn(_) | ast::Item::Static(_) | ast::Item::Const(_))
     })
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs
index 83f4a6b123c..3c84f83906a 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs
@@ -163,8 +163,8 @@ fn edit_struct_references(
                     // this also includes method calls like Foo::new(42), we should skip them
                     if let Some(name_ref) = path.segment().and_then(|s| s.name_ref()) {
                         match NameRefClass::classify(&ctx.sema, &name_ref) {
-                            Some(NameRefClass::Definition(Definition::SelfType(_))) => {},
-                            Some(NameRefClass::Definition(def)) if def == strukt_def => {},
+                            Some(NameRefClass::Definition(Definition::SelfType(_), _)) => {},
+                            Some(NameRefClass::Definition(def, _)) if def == strukt_def => {},
                             _ => return None,
                         };
                     }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs
index 22a1efdbea7..e34e5090487 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs
@@ -96,8 +96,7 @@ fn collect_data(ident_pat: ast::IdentPat, ctx: &AssistContext<'_>) -> Option<Str
     let struct_def_path = module.find_path(ctx.db(), struct_def, cfg)?;
 
     let is_non_exhaustive = struct_def.attrs(ctx.db())?.by_key(&sym::non_exhaustive).exists();
-    let is_foreign_crate =
-        struct_def.module(ctx.db()).map_or(false, |m| m.krate() != module.krate());
+    let is_foreign_crate = struct_def.module(ctx.db()).is_some_and(|m| m.krate() != module.krate());
 
     let fields = struct_type.fields(ctx.db());
     let n_fields = fields.len();
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs
index b9142d0318a..7df6ca1565f 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_tuple_binding.rs
@@ -6,7 +6,6 @@ use ide_db::{
     text_edit::TextRange,
 };
 use itertools::Itertools;
-use syntax::SmolStr;
 use syntax::{
     ast::{self, make, AstNode, FieldExpr, HasName, IdentPat},
     ted,
@@ -134,17 +133,8 @@ fn collect_data(ident_pat: IdentPat, ctx: &AssistContext<'_>) -> Option<TupleDat
             .map(|(_, refs)| refs.to_vec())
     });
 
-    let mut name_generator = {
-        let mut names = vec![];
-        if let Some(scope) = ctx.sema.scope(ident_pat.syntax()) {
-            scope.process_all_names(&mut |name, scope| {
-                if let hir::ScopeDef::Local(_) = scope {
-                    names.push(name.as_str().into())
-                }
-            })
-        }
-        suggest_name::NameGenerator::new_with_names(names.iter().map(|s: &SmolStr| s.as_str()))
-    };
+    let mut name_generator =
+        suggest_name::NameGenerator::new_from_scope_locals(ctx.sema.scope(ident_pat.syntax()));
 
     let field_names = field_types
         .into_iter()
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_glob_import.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_glob_import.rs
index 3d6d37ad93d..094fdc46eb7 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_glob_import.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_glob_import.rs
@@ -275,6 +275,7 @@ fn find_imported_defs(ctx: &AssistContext<'_>, star: SyntaxToken) -> Option<Vec<
                     | Definition::Static(_)
                     | Definition::Trait(_)
                     | Definition::TypeAlias(_)),
+                    _,
                 ) => Some(def),
                 _ => None,
             })
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 438769a0a87..0d1b6af7204 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
@@ -800,8 +800,8 @@ impl FunctionBody {
             let local_ref =
                 match name_ref.and_then(|name_ref| NameRefClass::classify(sema, &name_ref)) {
                     Some(
-                        NameRefClass::Definition(Definition::Local(local_ref))
-                        | NameRefClass::FieldShorthand { local_ref, field_ref: _ },
+                        NameRefClass::Definition(Definition::Local(local_ref), _)
+                        | NameRefClass::FieldShorthand { local_ref, field_ref: _, adt_subst: _ },
                     ) => local_ref,
                     _ => return,
                 };
@@ -856,7 +856,7 @@ impl FunctionBody {
         let mut set_parent_loop = |loop_: &dyn ast::HasLoopBody| {
             if loop_
                 .loop_body()
-                .map_or(false, |it| it.syntax().text_range().contains_range(self.text_range()))
+                .is_some_and(|it| it.syntax().text_range().contains_range(self.text_range()))
             {
                 parent_loop.get_or_insert(loop_.syntax().clone());
             }
@@ -1090,7 +1090,7 @@ impl FunctionBody {
                 let defined_outside_parent_loop = container_info
                     .parent_loop
                     .as_ref()
-                    .map_or(true, |it| it.text_range().contains_range(src.syntax().text_range()));
+                    .is_none_or(|it| it.text_range().contains_range(src.syntax().text_range()));
 
                 let is_copy = ty.is_copy(ctx.db());
                 let has_usages = self.has_usages_after_body(&usages);
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_module.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_module.rs
index e4cba666af7..6e3be0ce692 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_module.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_module.rs
@@ -425,7 +425,9 @@ impl Module {
                         })
                     } else if let Some(name_ref) = ast::NameRef::cast(x) {
                         NameRefClass::classify(&ctx.sema, &name_ref).and_then(|nc| match nc {
-                            NameRefClass::Definition(def) => Some((name_ref.syntax().clone(), def)),
+                            NameRefClass::Definition(def, _) => {
+                                Some((name_ref.syntax().clone(), def))
+                            }
                             _ => None,
                         })
                     } else {
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs
index 1eaf31628f3..67b8f5e5050 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_type_alias.rs
@@ -100,7 +100,7 @@ fn collect_used_generics<'gp>(
     fn find_lifetime(text: &str) -> impl Fn(&&ast::GenericParam) -> bool + '_ {
         move |gp: &&ast::GenericParam| match gp {
             ast::GenericParam::LifetimeParam(lp) => {
-                lp.lifetime().map_or(false, |lt| lt.text() == text)
+                lp.lifetime().is_some_and(|lt| lt.text() == text)
             }
             _ => false,
         }
@@ -118,7 +118,7 @@ fn collect_used_generics<'gp>(
                                 ast::GenericParam::TypeParam(tp) => tp.name(),
                                 _ => None,
                             }
-                            .map_or(false, |n| n.text() == name_ref.text())
+                            .is_some_and(|n| n.text() == name_ref.text())
                         }) {
                             generics.push(param);
                         }
@@ -165,7 +165,7 @@ fn collect_used_generics<'gp>(
                         if let Some(name_ref) = path.as_single_name_ref() {
                             if let Some(param) = known_generics.iter().find(|gp| {
                                 if let ast::GenericParam::ConstParam(cp) = gp {
-                                    cp.name().map_or(false, |n| n.text() == name_ref.text())
+                                    cp.name().is_some_and(|n| n.text() == name_ref.text())
                                 } else {
                                     false
                                 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs
index 6735d7dcbe1..0cc807aff64 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_variable.rs
@@ -99,7 +99,7 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
 
     let parent = to_extract.syntax().parent().and_then(ast::Expr::cast);
     // Any expression that autoderefs may need adjustment.
-    let mut needs_adjust = parent.as_ref().map_or(false, |it| match it {
+    let mut needs_adjust = parent.as_ref().is_some_and(|it| match it {
         ast::Expr::FieldExpr(_)
         | ast::Expr::MethodCallExpr(_)
         | ast::Expr::CallExpr(_)
@@ -336,10 +336,12 @@ impl ExtractionKind {
             }
         }
 
+        let mut name_generator =
+            suggest_name::NameGenerator::new_from_scope_locals(ctx.sema.scope(to_extract.syntax()));
         let var_name = if let Some(literal_name) = get_literal_name(ctx, to_extract) {
-            literal_name
+            name_generator.suggest_name(&literal_name)
         } else {
-            suggest_name::for_variable(to_extract, &ctx.sema)
+            name_generator.for_variable(to_extract, &ctx.sema)
         };
 
         let var_name = match self {
@@ -352,10 +354,10 @@ impl ExtractionKind {
 }
 
 fn get_literal_name(ctx: &AssistContext<'_>, expr: &ast::Expr) -> Option<String> {
-    let literal = match expr {
-        ast::Expr::Literal(literal) => literal,
-        _ => return None,
+    let ast::Expr::Literal(literal) = expr else {
+        return None;
     };
+
     let inner = match literal.kind() {
         ast::LiteralKind::String(string) => string.value().ok()?.into_owned(),
         ast::LiteralKind::ByteString(byte_string) => {
@@ -2632,4 +2634,33 @@ fn foo() {
             "Extract into static",
         );
     }
+
+    #[test]
+    fn extract_variable_name_conflicts() {
+        check_assist_by_label(
+            extract_variable,
+            r#"
+struct S { x: i32 };
+
+fn main() {
+    let s = 2;
+    let t = $0S { x: 1 }$0;
+    let t2 = t;
+    let x = s;
+}
+"#,
+            r#"
+struct S { x: i32 };
+
+fn main() {
+    let s = 2;
+    let $0s1 = S { x: 1 };
+    let t = s1;
+    let t2 = t;
+    let x = s;
+}
+"#,
+            "Extract into variable",
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_constant.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_constant.rs
index 25076dd5255..7f7db07152d 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_constant.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_constant.rs
@@ -64,7 +64,7 @@ pub(crate) fn generate_constant(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
         let name_ref_value = name_ref?;
         let name_ref_class = NameRefClass::classify(&ctx.sema, &name_ref_value);
         match name_ref_class {
-            Some(NameRefClass::Definition(Definition::Module(m))) => {
+            Some(NameRefClass::Definition(Definition::Module(m), _)) => {
                 if !m.visibility(ctx.sema.db).is_visible_from(ctx.sema.db, constant_module.into()) {
                     return None;
                 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_fn_type_alias.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_fn_type_alias.rs
index f4b4c22d98d..9d01ec00f83 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_fn_type_alias.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_fn_type_alias.rs
@@ -85,7 +85,6 @@ pub(crate) fn generate_fn_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>)
 
                 let is_unsafe = func_node.unsafe_token().is_some();
                 let ty = make::ty_fn_ptr(
-                    None,
                     is_unsafe,
                     func_node.abi(),
                     fn_params_vec.into_iter(),
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs
index 7b95c124e62..8f5daa4125a 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_function.rs
@@ -1077,7 +1077,7 @@ fn fn_arg_name(sema: &Semantics<'_, RootDatabase>, arg_expr: &ast::Expr) -> Stri
                 .filter_map(ast::NameRef::cast)
                 .filter(|name| name.ident_token().is_some())
                 .last()?;
-            if let Some(NameRefClass::Definition(Definition::Const(_) | Definition::Static(_))) =
+            if let Some(NameRefClass::Definition(Definition::Const(_) | Definition::Static(_), _)) =
                 NameRefClass::classify(sema, &name_ref)
             {
                 return Some(name_ref.to_string().to_lowercase());
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_bounds.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_bounds.rs
index 1dd376ac3fd..5101d8fa0a9 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_bounds.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_bounds.rs
@@ -78,7 +78,7 @@ pub(crate) fn move_bounds_to_where_clause(
 
 fn build_predicate(param: ast::TypeParam) -> Option<ast::WherePred> {
     let path = make::ext::ident_path(&param.name()?.syntax().to_string());
-    let predicate = make::where_pred(path, param.type_bound_list()?.bounds());
+    let predicate = make::where_pred(make::ty_path(path), param.type_bound_list()?.bounds());
     Some(predicate.clone_for_update())
 }
 
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_param.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_param.rs
index 376243c2681..75120768da0 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_param.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_param.rs
@@ -47,7 +47,7 @@ pub(crate) fn remove_unused_param(acc: &mut Assists, ctx: &AssistContext<'_>) ->
         .parent() // AssocItemList
         .and_then(|x| x.parent())
         .and_then(ast::Impl::cast)
-        .map_or(false, |imp| imp.trait_().is_some())
+        .is_some_and(|imp| imp.trait_().is_some())
     {
         cov_mark::hit!(trait_impl);
         return None;
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs
index 56dd6cf29ae..b31d45e6d45 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_if_let_with_match.rs
@@ -17,7 +17,7 @@ use syntax::{
 };
 
 use crate::{
-    utils::{does_nested_pattern, does_pat_match_variant, unwrap_trivial_block},
+    utils::{does_pat_match_variant, does_pat_variant_nested_or_literal, unwrap_trivial_block},
     AssistContext, AssistId, AssistKind, Assists,
 };
 
@@ -135,7 +135,7 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext<'
             };
 
             let has_preceding_if_expr =
-                if_expr.syntax().parent().map_or(false, |it| ast::IfExpr::can_cast(it.kind()));
+                if_expr.syntax().parent().is_some_and(|it| ast::IfExpr::can_cast(it.kind()));
             let expr = if has_preceding_if_expr {
                 // make sure we replace the `else if let ...` with a block so we don't end up with `else expr`
                 make::block_expr(None, Some(match_expr)).into()
@@ -163,7 +163,7 @@ fn make_else_arm(
                 Some(it) => {
                     if does_pat_match_variant(pat, &it.sad_pattern()) {
                         it.happy_pattern_wildcard()
-                    } else if does_nested_pattern(pat) {
+                    } else if does_pat_variant_nested_or_literal(ctx, pat) {
                         make::wildcard_pat().into()
                     } else {
                         it.sad_pattern()
@@ -241,7 +241,7 @@ pub(crate) fn replace_match_with_if_let(acc: &mut Assists, ctx: &AssistContext<'
         ast::Pat::LiteralPat(p)
             if p.literal()
                 .map(|it| it.token().kind())
-                .map_or(false, |it| it == T![true] || it == T![false]) =>
+                .is_some_and(|it| it == T![true] || it == T![false]) =>
         {
             ""
         }
@@ -265,12 +265,12 @@ pub(crate) fn replace_match_with_if_let(acc: &mut Assists, ctx: &AssistContext<'
 
             let condition = match if_let_pat {
                 ast::Pat::LiteralPat(p)
-                    if p.literal().map_or(false, |it| it.token().kind() == T![true]) =>
+                    if p.literal().is_some_and(|it| it.token().kind() == T![true]) =>
                 {
                     scrutinee
                 }
                 ast::Pat::LiteralPat(p)
-                    if p.literal().map_or(false, |it| it.token().kind() == T![false]) =>
+                    if p.literal().is_some_and(|it| it.token().kind() == T![false]) =>
                 {
                     make::expr_prefix(T![!], scrutinee)
                 }
@@ -339,10 +339,10 @@ fn binds_name(sema: &hir::Semantics<'_, RootDatabase>, pat: &ast::Pat) -> bool {
         ast::Pat::TupleStructPat(it) => it.fields().any(binds_name_v),
         ast::Pat::RecordPat(it) => it
             .record_pat_field_list()
-            .map_or(false, |rpfl| rpfl.fields().flat_map(|rpf| rpf.pat()).any(binds_name_v)),
-        ast::Pat::RefPat(pat) => pat.pat().map_or(false, binds_name_v),
-        ast::Pat::BoxPat(pat) => pat.pat().map_or(false, binds_name_v),
-        ast::Pat::ParenPat(pat) => pat.pat().map_or(false, binds_name_v),
+            .is_some_and(|rpfl| rpfl.fields().flat_map(|rpf| rpf.pat()).any(binds_name_v)),
+        ast::Pat::RefPat(pat) => pat.pat().is_some_and(binds_name_v),
+        ast::Pat::BoxPat(pat) => pat.pat().is_some_and(binds_name_v),
+        ast::Pat::ParenPat(pat) => pat.pat().is_some_and(binds_name_v),
         _ => false,
     }
 }
@@ -350,7 +350,7 @@ fn binds_name(sema: &hir::Semantics<'_, RootDatabase>, pat: &ast::Pat) -> bool {
 fn is_sad_pat(sema: &hir::Semantics<'_, RootDatabase>, pat: &ast::Pat) -> bool {
     sema.type_of_pat(pat)
         .and_then(|ty| TryEnum::from_ty(sema, &ty.adjusted()))
-        .map_or(false, |it| does_pat_match_variant(pat, &it.sad_pattern()))
+        .is_some_and(|it| does_pat_match_variant(pat, &it.sad_pattern()))
 }
 
 #[cfg(test)]
@@ -702,11 +702,11 @@ fn main() {
     }
 
     #[test]
-    fn nested_type() {
+    fn test_if_let_with_match_nested_tuple_struct() {
         check_assist(
             replace_if_let_with_match,
             r#"
-//- minicore: result
+//- minicore: result, option
 fn foo(x: Result<i32, ()>) {
     let bar: Result<_, ()> = Ok(Some(1));
     $0if let Ok(Some(_)) = bar {
@@ -726,6 +726,700 @@ fn foo(x: Result<i32, ()>) {
 }
 "#,
         );
+
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+//- minicore: result
+struct MyStruct(i32, i32);
+fn foo(x: Result<MyStruct, ()>) {
+    let bar: Result<MyStruct, ()> = Ok(MyStruct(1, 2));
+    $0if let Ok(MyStruct(a, b)) = bar {
+        ()
+    } else {
+        ()
+    }
+}
+"#,
+            r#"
+struct MyStruct(i32, i32);
+fn foo(x: Result<MyStruct, ()>) {
+    let bar: Result<MyStruct, ()> = Ok(MyStruct(1, 2));
+    match bar {
+        Ok(MyStruct(a, b)) => (),
+        Err(_) => (),
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn test_if_let_with_match_nested_slice() {
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+//- minicore: result
+fn foo(x: Result<&[i32], ()>) {
+    let foo: Result<&[_], ()> = Ok(&[0, 1, 2]);
+    $0if let Ok([]) = foo {
+        ()
+    } else {
+        ()
+    }
+}
+        "#,
+            r#"
+fn foo(x: Result<&[i32], ()>) {
+    let foo: Result<&[_], ()> = Ok(&[0, 1, 2]);
+    match foo {
+        Ok([]) => (),
+        _ => (),
+    }
+}
+        "#,
+        );
+
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+//- minicore: result
+fn foo(x: Result<[&'static str; 2], ()>) {
+    let foobar: Result<_, ()> = Ok(["foo", "bar"]);
+    $0if let Ok([_, "bar"]) = foobar {
+        ()
+    } else {
+        ()
+    }
+}
+"#,
+            r#"
+fn foo(x: Result<[&'static str; 2], ()>) {
+    let foobar: Result<_, ()> = Ok(["foo", "bar"]);
+    match foobar {
+        Ok([_, "bar"]) => (),
+        _ => (),
+    }
+}
+"#,
+        );
+
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+//- minicore: result
+fn foo(x: Result<[&'static str; 2], ()>) {
+    let foobar: Result<_, ()> = Ok(["foo", "bar"]);
+    $0if let Ok([..]) = foobar {
+        ()
+    } else {
+        ()
+    }
+}
+"#,
+            r#"
+fn foo(x: Result<[&'static str; 2], ()>) {
+    let foobar: Result<_, ()> = Ok(["foo", "bar"]);
+    match foobar {
+        Ok([..]) => (),
+        Err(_) => (),
+    }
+}
+"#,
+        );
+
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+//- minicore: result
+fn foo(x: Result<&[&'static str], ()>) {
+    let foobar: Result<&[&'static str], ()> = Ok(&["foo", "bar"]);
+    $0if let Ok([a, ..]) = foobar {
+        ()
+    } else {
+        ()
+    }
+}
+"#,
+            r#"
+fn foo(x: Result<&[&'static str], ()>) {
+    let foobar: Result<&[&'static str], ()> = Ok(&["foo", "bar"]);
+    match foobar {
+        Ok([a, ..]) => (),
+        _ => (),
+    }
+}
+"#,
+        );
+
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+//- minicore: result
+fn foo(x: Result<&[&'static str], ()>) {
+    let foobar: Result<&[&'static str], ()> = Ok(&["foo", "bar"]);
+    $0if let Ok([a, .., b, c]) = foobar {
+        ()
+    } else {
+        ()
+    }
+}
+"#,
+            r#"
+fn foo(x: Result<&[&'static str], ()>) {
+    let foobar: Result<&[&'static str], ()> = Ok(&["foo", "bar"]);
+    match foobar {
+        Ok([a, .., b, c]) => (),
+        _ => (),
+    }
+}
+"#,
+        );
+
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+//- minicore: result
+fn foo(x: Result<Option<[&'static str; 2]>, ()>) {
+    let foobar: Result<_, ()> = Ok(Some(["foo", "bar"]));
+    $0if let Ok(Some([_, "bar"])) = foobar {
+        ()
+    } else {
+        ()
+    }
+}
+"#,
+            r#"
+fn foo(x: Result<Option<[&'static str; 2]>, ()>) {
+    let foobar: Result<_, ()> = Ok(Some(["foo", "bar"]));
+    match foobar {
+        Ok(Some([_, "bar"])) => (),
+        _ => (),
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn test_if_let_with_match_nested_literal() {
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+//- minicore: result
+fn foo(x: Result<&'static str, ()>) {
+    let bar: Result<&_, ()> = Ok("bar");
+    $0if let Ok("foo") = bar {
+        ()
+    } else {
+        ()
+    }
+}
+"#,
+            r#"
+fn foo(x: Result<&'static str, ()>) {
+    let bar: Result<&_, ()> = Ok("bar");
+    match bar {
+        Ok("foo") => (),
+        _ => (),
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn test_if_let_with_match_nested_tuple() {
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+//- minicore: result
+fn foo(x: Result<(i32, i32, i32), ()>) {
+    let bar: Result<(i32, i32, i32), ()> = Ok((1, 2, 3));
+    $0if let Ok((1, second, third)) = bar {
+        ()
+    } else {
+        ()
+    }
+}
+"#,
+            r#"
+fn foo(x: Result<(i32, i32, i32), ()>) {
+    let bar: Result<(i32, i32, i32), ()> = Ok((1, 2, 3));
+    match bar {
+        Ok((1, second, third)) => (),
+        _ => (),
+    }
+}
+"#,
+        );
+
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+//- minicore: result
+fn foo(x: Result<(i32, i32, i32), ()>) {
+    let bar: Result<(i32, i32, i32), ()> = Ok((1, 2, 3));
+    $0if let Ok((first, second, third)) = bar {
+        ()
+    } else {
+        ()
+    }
+}
+"#,
+            r#"
+fn foo(x: Result<(i32, i32, i32), ()>) {
+    let bar: Result<(i32, i32, i32), ()> = Ok((1, 2, 3));
+    match bar {
+        Ok((first, second, third)) => (),
+        Err(_) => (),
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn test_if_let_with_match_nested_or() {
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+//- minicore: result
+fn foo(x: Result<i32, ()>) {
+    let bar: Result<i32, ()> = Ok(1);
+    $0if let Ok(1 | 2) = bar {
+        ()
+    } else {
+        ()
+    }
+}
+"#,
+            r#"
+fn foo(x: Result<i32, ()>) {
+    let bar: Result<i32, ()> = Ok(1);
+    match bar {
+        Ok(1 | 2) => (),
+        _ => (),
+    }
+}
+"#,
+        );
+
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+//- minicore: result
+fn foo(x: Result<(i32, i32), ()>) {
+    let bar: Result<(i32, i32), ()> = Ok((1, 2));
+    $0if let Ok((b, a) | (a, b)) = bar {
+        ()
+    } else {
+        ()
+    }
+}
+"#,
+            r#"
+fn foo(x: Result<(i32, i32), ()>) {
+    let bar: Result<(i32, i32), ()> = Ok((1, 2));
+    match bar {
+        Ok((b, a) | (a, b)) => (),
+        Err(_) => (),
+    }
+}
+"#,
+        );
+
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+//- minicore: result
+fn foo(x: Result<(i32, i32), ()>) {
+    let bar: Result<(i32, i32), ()> = Ok((1, 2));
+    $0if let Ok((1, a) | (a, 2)) = bar {
+        ()
+    } else {
+        ()
+    }
+}
+"#,
+            r#"
+fn foo(x: Result<(i32, i32), ()>) {
+    let bar: Result<(i32, i32), ()> = Ok((1, 2));
+    match bar {
+        Ok((1, a) | (a, 2)) => (),
+        _ => (),
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn test_if_let_with_match_nested_range() {
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+//- minicore: result
+fn foo(x: Result<i32, ()>) {
+    let bar: Result<i32, ()> = Ok(1);
+    $0if let Ok(1..2) = bar {
+        ()
+    } else {
+        ()
+    }
+}
+"#,
+            r#"
+fn foo(x: Result<i32, ()>) {
+    let bar: Result<i32, ()> = Ok(1);
+    match bar {
+        Ok(1..2) => (),
+        _ => (),
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn test_if_let_with_match_nested_paren() {
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+//- minicore: result
+fn foo(x: Result<(i32, i32), ()>) {
+    let bar: Result<(i32, i32), ()> = Ok((1, 1));
+    $0if let Ok(((1, 2))) = bar {
+        ()
+    } else {
+        ()
+    }
+}
+"#,
+            r#"
+fn foo(x: Result<(i32, i32), ()>) {
+    let bar: Result<(i32, i32), ()> = Ok((1, 1));
+    match bar {
+        Ok(((1, 2))) => (),
+        _ => (),
+    }
+}
+"#,
+        );
+
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+//- minicore: result
+fn foo(x: Result<(i32, i32), ()>) {
+    let bar: Result<(i32, i32), ()> = Ok((1, 1));
+    $0if let Ok(((a, b))) = bar {
+        ()
+    } else {
+        ()
+    }
+}
+"#,
+            r#"
+fn foo(x: Result<(i32, i32), ()>) {
+    let bar: Result<(i32, i32), ()> = Ok((1, 1));
+    match bar {
+        Ok(((a, b))) => (),
+        Err(_) => (),
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn test_if_let_with_match_nested_macro() {
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+//- minicore: result
+fn foo(x: Result<i32, ()>) {
+    macro_rules! is_42 {
+        () => {
+            42
+        };
+    }
+
+    let bar: Result<i32, ()> = Ok(1);
+    $0if let Ok(is_42!()) = bar {
+        ()
+    } else {
+        ()
+    }
+}
+"#,
+            r#"
+fn foo(x: Result<i32, ()>) {
+    macro_rules! is_42 {
+        () => {
+            42
+        };
+    }
+
+    let bar: Result<i32, ()> = Ok(1);
+    match bar {
+        Ok(is_42!()) => (),
+        _ => (),
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn test_if_let_with_match_nested_path() {
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+//- minicore: result
+enum MyEnum {
+    Foo,
+    Bar,
+}
+
+fn foo(x: Result<MyEnum, ()>) {
+    let bar: Result<MyEnum, ()> = Ok(MyEnum::Foo);
+    $0if let Ok(MyEnum::Foo) = bar {
+        ()
+    } else {
+        ()
+    }
+}
+"#,
+            r#"
+enum MyEnum {
+    Foo,
+    Bar,
+}
+
+fn foo(x: Result<MyEnum, ()>) {
+    let bar: Result<MyEnum, ()> = Ok(MyEnum::Foo);
+    match bar {
+        Ok(MyEnum::Foo) => (),
+        _ => (),
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn test_if_let_with_match_nested_record() {
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+//- minicore: result
+struct MyStruct {
+    foo: i32,
+    bar: i32,
+}
+
+fn foo(x: Result<MyStruct, ()>) {
+    let bar: Result<MyStruct, ()> = Ok(MyStruct { foo: 1, bar: 2 });
+    $0if let Ok(MyStruct { foo, bar }) = bar {
+        ()
+    } else {
+        ()
+    }
+}
+"#,
+            r#"
+struct MyStruct {
+    foo: i32,
+    bar: i32,
+}
+
+fn foo(x: Result<MyStruct, ()>) {
+    let bar: Result<MyStruct, ()> = Ok(MyStruct { foo: 1, bar: 2 });
+    match bar {
+        Ok(MyStruct { foo, bar }) => (),
+        Err(_) => (),
+    }
+}
+"#,
+        );
+
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+//- minicore: result
+struct MyStruct {
+    foo: i32,
+    bar: i32,
+}
+
+fn foo(x: Result<MyStruct, ()>) {
+    let bar: Result<MyStruct, ()> = Ok(MyStruct { foo: 1, bar: 2 });
+    $0if let Ok(MyStruct { foo, bar: 12 }) = bar {
+        ()
+    } else {
+        ()
+    }
+}
+"#,
+            r#"
+struct MyStruct {
+    foo: i32,
+    bar: i32,
+}
+
+fn foo(x: Result<MyStruct, ()>) {
+    let bar: Result<MyStruct, ()> = Ok(MyStruct { foo: 1, bar: 2 });
+    match bar {
+        Ok(MyStruct { foo, bar: 12 }) => (),
+        _ => (),
+    }
+}
+"#,
+        );
+
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+//- minicore: result
+struct MyStruct {
+    foo: i32,
+    bar: i32,
+}
+
+fn foo(x: Result<MyStruct, ()>) {
+    let bar: Result<MyStruct, ()> = Ok(MyStruct { foo: 1, bar: 2 });
+    $0if let Ok(MyStruct { foo, .. }) = bar {
+        ()
+    } else {
+        ()
+    }
+}
+"#,
+            r#"
+struct MyStruct {
+    foo: i32,
+    bar: i32,
+}
+
+fn foo(x: Result<MyStruct, ()>) {
+    let bar: Result<MyStruct, ()> = Ok(MyStruct { foo: 1, bar: 2 });
+    match bar {
+        Ok(MyStruct { foo, .. }) => (),
+        Err(_) => (),
+    }
+}
+"#,
+        );
+
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+//- minicore: result
+enum MyEnum {
+    Foo(i32, i32),
+    Bar { a: i32, b: i32 },
+}
+
+fn foo(x: Result<MyEnum, ()>) {
+    let bar: Result<MyEnum, ()> = Ok(MyEnum::Foo(1, 2));
+    $0if let Ok(MyEnum::Bar { a, b }) = bar {
+        ()
+    } else {
+        ()
+    }
+}
+"#,
+            r#"
+enum MyEnum {
+    Foo(i32, i32),
+    Bar { a: i32, b: i32 },
+}
+
+fn foo(x: Result<MyEnum, ()>) {
+    let bar: Result<MyEnum, ()> = Ok(MyEnum::Foo(1, 2));
+    match bar {
+        Ok(MyEnum::Bar { a, b }) => (),
+        _ => (),
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn test_if_let_with_match_nested_ident() {
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+//- minicore: result
+fn foo(x: Result<i32, ()>) {
+    let bar: Result<i32, ()> = Ok(1);
+    $0if let Ok(a @ 1..2) = bar {
+        ()
+    } else {
+        ()
+    }
+}
+"#,
+            r#"
+fn foo(x: Result<i32, ()>) {
+    let bar: Result<i32, ()> = Ok(1);
+    match bar {
+        Ok(a @ 1..2) => (),
+        _ => (),
+    }
+}
+"#,
+        );
+
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+//- minicore: result
+fn foo(x: Result<i32, ()>) {
+    let bar: Result<i32, ()> = Ok(1);
+    $0if let Ok(a) = bar {
+        ()
+    } else {
+        ()
+    }
+}
+"#,
+            r#"
+fn foo(x: Result<i32, ()>) {
+    let bar: Result<i32, ()> = Ok(1);
+    match bar {
+        Ok(a) => (),
+        Err(_) => (),
+    }
+}
+"#,
+        );
+
+        check_assist(
+            replace_if_let_with_match,
+            r#"
+//- minicore: result
+fn foo(x: Result<i32, ()>) {
+    let bar: Result<i32, ()> = Ok(1);
+    $0if let Ok(a @ b @ c @ d) = bar {
+        ()
+    } else {
+        ()
+    }
+}
+"#,
+            r#"
+fn foo(x: Result<i32, ()>) {
+    let bar: Result<i32, ()> = Ok(1);
+    match bar {
+        Ok(a @ b @ c @ d) => (),
+        Err(_) => (),
+    }
+}
+"#,
+        );
     }
 
     #[test]
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs
index a856da09215..47972ff619a 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_is_method_with_if_let_method.rs
@@ -20,7 +20,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
 // ```
 // fn main() {
 //     let x = Some(1);
-//     if let Some(${0:x}) = x {}
+//     if let Some(${0:x1}) = x {}
 // }
 // ```
 pub(crate) fn replace_is_method_with_if_let_method(
@@ -40,10 +40,13 @@ pub(crate) fn replace_is_method_with_if_let_method(
         "is_some" | "is_ok" => {
             let receiver = call_expr.receiver()?;
 
+            let mut name_generator = suggest_name::NameGenerator::new_from_scope_locals(
+                ctx.sema.scope(if_expr.syntax()),
+            );
             let var_name = if let ast::Expr::PathExpr(path_expr) = receiver.clone() {
-                path_expr.path()?.to_string()
+                name_generator.suggest_name(&path_expr.path()?.to_string())
             } else {
-                suggest_name::for_variable(&receiver, &ctx.sema)
+                name_generator.for_variable(&receiver, &ctx.sema)
             };
 
             let (assist_id, message, text) = if name_ref.text() == "is_some" {
@@ -98,7 +101,7 @@ fn main() {
             r#"
 fn main() {
     let x = Some(1);
-    if let Some(${0:x}) = x {}
+    if let Some(${0:x1}) = x {}
 }
 "#,
         );
@@ -150,7 +153,7 @@ fn main() {
             r#"
 fn main() {
     let x = Ok(1);
-    if let Ok(${0:x}) = x {}
+    if let Ok(${0:x1}) = x {}
 }
 "#,
         );
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs
index 1101c20f1b7..f026b3230dd 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/replace_qualified_name_with_use.rs
@@ -159,7 +159,7 @@ fn path_eq_no_generics(lhs: ast::Path, rhs: ast::Path) -> bool {
                     && lhs
                         .name_ref()
                         .zip(rhs.name_ref())
-                        .map_or(false, |(lhs, rhs)| lhs.text() == rhs.text()) => {}
+                        .is_some_and(|(lhs, rhs)| lhs.text() == rhs.text()) => {}
             _ => return false,
         }
 
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs
index 648bf358b4b..c6cffb5434a 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_match_arm.rs
@@ -65,7 +65,7 @@ pub(crate) fn unmerge_match_arm(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
             let mut pipe_index = pipe_token.index();
             if pipe_token
                 .prev_sibling_or_token()
-                .map_or(false, |it| it.kind() == SyntaxKind::WHITESPACE)
+                .is_some_and(|it| it.kind() == SyntaxKind::WHITESPACE)
             {
                 pipe_index -= 1;
             }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs
index 52df30d9623..38ca572fa66 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unmerge_use.rs
@@ -66,7 +66,7 @@ fn resolve_full_path(tree: &ast::UseTree) -> Option<ast::Path> {
         .filter_map(|t| t.path());
 
     let final_path = paths.reduce(|prev, next| make::path_concat(next, prev))?;
-    if final_path.segment().map_or(false, |it| it.self_token().is_some()) {
+    if final_path.segment().is_some_and(|it| it.self_token().is_some()) {
         final_path.qualifier()
     } else {
         Some(final_path)
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
index 78fdfba6a07..54e42f126bc 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
@@ -2885,7 +2885,7 @@ fn main() {
         r#####"
 fn main() {
     let x = Some(1);
-    if let Some(${0:x}) = x {}
+    if let Some(${0:x1}) = x {}
 }
 "#####,
     )
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs
index 3c26b043597..e20c4ef09e8 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs
@@ -316,43 +316,73 @@ pub(crate) fn does_pat_match_variant(pat: &ast::Pat, var: &ast::Pat) -> bool {
     pat_head == var_head
 }
 
-pub(crate) fn does_nested_pattern(pat: &ast::Pat) -> bool {
-    let depth = calc_depth(pat, 0);
+pub(crate) fn does_pat_variant_nested_or_literal(ctx: &AssistContext<'_>, pat: &ast::Pat) -> bool {
+    check_pat_variant_nested_or_literal_with_depth(ctx, pat, 0)
+}
+
+fn check_pat_variant_from_enum(ctx: &AssistContext<'_>, pat: &ast::Pat) -> bool {
+    ctx.sema.type_of_pat(pat).is_none_or(|ty: hir::TypeInfo| {
+        ty.adjusted().as_adt().is_some_and(|adt| matches!(adt, hir::Adt::Enum(_)))
+    })
+}
 
-    if 1 < depth {
+fn check_pat_variant_nested_or_literal_with_depth(
+    ctx: &AssistContext<'_>,
+    pat: &ast::Pat,
+    depth_after_refutable: usize,
+) -> bool {
+    if depth_after_refutable > 1 {
         return true;
     }
-    false
-}
 
-fn calc_depth(pat: &ast::Pat, depth: usize) -> usize {
     match pat {
-        ast::Pat::IdentPat(_)
-        | ast::Pat::BoxPat(_)
-        | ast::Pat::RestPat(_)
-        | ast::Pat::LiteralPat(_)
+        ast::Pat::RestPat(_) | ast::Pat::WildcardPat(_) | ast::Pat::RefPat(_) => false,
+
+        ast::Pat::LiteralPat(_)
+        | ast::Pat::RangePat(_)
         | ast::Pat::MacroPat(_)
-        | ast::Pat::OrPat(_)
-        | ast::Pat::ParenPat(_)
         | ast::Pat::PathPat(_)
-        | ast::Pat::WildcardPat(_)
-        | ast::Pat::RangePat(_)
-        | ast::Pat::RecordPat(_)
-        | ast::Pat::RefPat(_)
-        | ast::Pat::SlicePat(_)
-        | ast::Pat::TuplePat(_)
-        | ast::Pat::ConstBlockPat(_) => depth,
-
-        // FIXME: Other patterns may also be nested. Currently it simply supports only `TupleStructPat`
-        ast::Pat::TupleStructPat(pat) => {
-            let mut max_depth = depth;
-            for p in pat.fields() {
-                let d = calc_depth(&p, depth + 1);
-                if d > max_depth {
-                    max_depth = d
-                }
-            }
-            max_depth
+        | ast::Pat::BoxPat(_)
+        | ast::Pat::ConstBlockPat(_) => true,
+
+        ast::Pat::IdentPat(ident_pat) => ident_pat.pat().is_some_and(|pat| {
+            check_pat_variant_nested_or_literal_with_depth(ctx, &pat, depth_after_refutable)
+        }),
+        ast::Pat::ParenPat(paren_pat) => paren_pat.pat().is_none_or(|pat| {
+            check_pat_variant_nested_or_literal_with_depth(ctx, &pat, depth_after_refutable)
+        }),
+        ast::Pat::TuplePat(tuple_pat) => tuple_pat.fields().any(|pat| {
+            check_pat_variant_nested_or_literal_with_depth(ctx, &pat, depth_after_refutable)
+        }),
+        ast::Pat::RecordPat(record_pat) => {
+            let adjusted_next_depth =
+                depth_after_refutable + if check_pat_variant_from_enum(ctx, pat) { 1 } else { 0 };
+            record_pat.record_pat_field_list().is_none_or(|pat| {
+                pat.fields().any(|pat| {
+                    pat.pat().is_none_or(|pat| {
+                        check_pat_variant_nested_or_literal_with_depth(
+                            ctx,
+                            &pat,
+                            adjusted_next_depth,
+                        )
+                    })
+                })
+            })
+        }
+        ast::Pat::OrPat(or_pat) => or_pat.pats().any(|pat| {
+            check_pat_variant_nested_or_literal_with_depth(ctx, &pat, depth_after_refutable)
+        }),
+        ast::Pat::TupleStructPat(tuple_struct_pat) => {
+            let adjusted_next_depth =
+                depth_after_refutable + if check_pat_variant_from_enum(ctx, pat) { 1 } else { 0 };
+            tuple_struct_pat.fields().any(|pat| {
+                check_pat_variant_nested_or_literal_with_depth(ctx, &pat, adjusted_next_depth)
+            })
+        }
+        ast::Pat::SlicePat(slice_pat) => {
+            let mut pats = slice_pat.pats();
+            pats.next()
+                .is_none_or(|pat| !matches!(pat, ast::Pat::RestPat(_)) || pats.next().is_some())
         }
     }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs b/src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs
index c5a91e478bf..75caf6d49f7 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils/gen_trait_fn_body.rs
@@ -32,7 +32,7 @@ pub(crate) fn gen_trait_fn_body(
 
 /// Generate a `Clone` impl based on the fields and members of the target type.
 fn gen_clone_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
-    stdx::always!(func.name().map_or(false, |name| name.text() == "clone"));
+    stdx::always!(func.name().is_some_and(|name| name.text() == "clone"));
     fn gen_clone_call(target: ast::Expr) -> ast::Expr {
         let method = make::name_ref("clone");
         make::expr_method_call(target, method, make::arg_list(None))
@@ -344,7 +344,7 @@ fn gen_default_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
 
 /// Generate a `Hash` impl based on the fields and members of the target type.
 fn gen_hash_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
-    stdx::always!(func.name().map_or(false, |name| name.text() == "hash"));
+    stdx::always!(func.name().is_some_and(|name| name.text() == "hash"));
     fn gen_hash_call(target: ast::Expr) -> ast::Stmt {
         let method = make::name_ref("hash");
         let arg = make::expr_path(make::ext::ident_path("state"));
@@ -400,7 +400,7 @@ fn gen_hash_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
 
 /// Generate a `PartialEq` impl based on the fields and members of the target type.
 fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn, trait_ref: Option<TraitRef>) -> Option<()> {
-    stdx::always!(func.name().map_or(false, |name| name.text() == "eq"));
+    stdx::always!(func.name().is_some_and(|name| name.text() == "eq"));
     fn gen_eq_chain(expr: Option<ast::Expr>, cmp: ast::Expr) -> Option<ast::Expr> {
         match expr {
             Some(expr) => Some(make::expr_bin_op(expr, BinaryOp::LogicOp(LogicOp::And), cmp)),
@@ -592,7 +592,7 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn, trait_ref: Option<TraitRef>) -
 }
 
 fn gen_partial_ord(adt: &ast::Adt, func: &ast::Fn, trait_ref: Option<TraitRef>) -> Option<()> {
-    stdx::always!(func.name().map_or(false, |name| name.text() == "partial_cmp"));
+    stdx::always!(func.name().is_some_and(|name| name.text() == "partial_cmp"));
     fn gen_partial_eq_match(match_target: ast::Expr) -> Option<ast::Stmt> {
         let mut arms = vec![];
 
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 229ce7723b5..26074672ba9 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
@@ -1,6 +1,8 @@
 //! Completes references after dot (fields and method calls).
 
-use hir::{sym, Name};
+use std::ops::ControlFlow;
+
+use hir::{sym, HasContainer, ItemContainer, MethodCandidateCallback, Name};
 use ide_db::FxHashSet;
 use syntax::SmolStr;
 
@@ -158,21 +160,55 @@ fn complete_fields(
 fn complete_methods(
     ctx: &CompletionContext<'_>,
     receiver: &hir::Type,
-    mut f: impl FnMut(hir::Function),
+    f: impl FnMut(hir::Function),
 ) {
-    let mut seen_methods = FxHashSet::default();
-    receiver.iterate_method_candidates_with_traits(
+    struct Callback<'a, F> {
+        ctx: &'a CompletionContext<'a>,
+        f: F,
+        seen_methods: FxHashSet<Name>,
+    }
+
+    impl<F> MethodCandidateCallback for Callback<'_, F>
+    where
+        F: FnMut(hir::Function),
+    {
+        // We don't want to exclude inherent trait methods - that is, methods of traits available from
+        // `where` clauses or `dyn Trait`.
+        fn on_inherent_method(&mut self, func: hir::Function) -> ControlFlow<()> {
+            if func.self_param(self.ctx.db).is_some()
+                && self.seen_methods.insert(func.name(self.ctx.db))
+            {
+                (self.f)(func);
+            }
+            ControlFlow::Continue(())
+        }
+
+        fn on_trait_method(&mut self, func: hir::Function) -> ControlFlow<()> {
+            // This needs to come before the `seen_methods` test, so that if we see the same method twice,
+            // once as inherent and once not, we will include it.
+            if let ItemContainer::Trait(trait_) = func.container(self.ctx.db) {
+                if self.ctx.exclude_traits.contains(&trait_) {
+                    return ControlFlow::Continue(());
+                }
+            }
+
+            if func.self_param(self.ctx.db).is_some()
+                && self.seen_methods.insert(func.name(self.ctx.db))
+            {
+                (self.f)(func);
+            }
+
+            ControlFlow::Continue(())
+        }
+    }
+
+    receiver.iterate_method_candidates_split_inherent(
         ctx.db,
         &ctx.scope,
         &ctx.traits_in_scope(),
         Some(ctx.module),
         None,
-        |func| {
-            if func.self_param(ctx.db).is_some() && seen_methods.insert(func.name(ctx.db)) {
-                f(func);
-            }
-            None::<()>
-        },
+        Callback { ctx, f, seen_methods: FxHashSet::default() },
     );
 }
 
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs
index c9013d1d17d..0b6790d42a6 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/env_vars.rs
@@ -43,7 +43,7 @@ pub(crate) fn complete_cargo_env_vars(
         .sema
         .hir_file_for(&expanded.syntax().parent()?)
         .macro_file()
-        .map_or(false, |it| it.is_env_or_option_env(ctx.sema.db));
+        .is_some_and(|it| it.is_env_or_option_env(ctx.sema.db));
     if !is_in_env_expansion {
         let call = macro_call_for_string_token(expanded)?;
         let makro = ctx.sema.resolve_macro_call(&call)?;
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs
index ff2c8da4213..c2e5eefe101 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs
@@ -1,6 +1,9 @@
 //! Completion of names from the current scope in expression position.
 
-use hir::{sym, Name, ScopeDef};
+use std::ops::ControlFlow;
+
+use hir::{sym, Name, PathCandidateCallback, ScopeDef};
+use ide_db::FxHashSet;
 use syntax::ast;
 
 use crate::{
@@ -9,6 +12,38 @@ use crate::{
     CompletionContext, Completions,
 };
 
+struct PathCallback<'a, F> {
+    ctx: &'a CompletionContext<'a>,
+    acc: &'a mut Completions,
+    add_assoc_item: F,
+    seen: FxHashSet<hir::AssocItem>,
+}
+
+impl<F> PathCandidateCallback for PathCallback<'_, F>
+where
+    F: FnMut(&mut Completions, hir::AssocItem),
+{
+    fn on_inherent_item(&mut self, item: hir::AssocItem) -> ControlFlow<()> {
+        if self.seen.insert(item) {
+            (self.add_assoc_item)(self.acc, item);
+        }
+        ControlFlow::Continue(())
+    }
+
+    fn on_trait_item(&mut self, item: hir::AssocItem) -> ControlFlow<()> {
+        // The excluded check needs to come before the `seen` test, so that if we see the same method twice,
+        // once as inherent and once not, we will include it.
+        if item
+            .container_trait(self.ctx.db)
+            .is_none_or(|trait_| !self.ctx.exclude_traits.contains(&trait_))
+            && self.seen.insert(item)
+        {
+            (self.add_assoc_item)(self.acc, item);
+        }
+        ControlFlow::Continue(())
+    }
+}
+
 pub(crate) fn complete_expr_path(
     acc: &mut Completions,
     ctx: &CompletionContext<'_>,
@@ -50,12 +85,18 @@ pub(crate) fn complete_expr_path(
     };
 
     match qualified {
+        // We exclude associated types/consts of excluded traits here together with methods,
+        // even though we don't exclude them when completing in type position, because it's easier.
         Qualified::TypeAnchor { ty: None, trait_: None } => ctx
             .traits_in_scope()
             .iter()
-            .flat_map(|&it| hir::Trait::from(it).items(ctx.sema.db))
+            .copied()
+            .map(hir::Trait::from)
+            .filter(|it| !ctx.exclude_traits.contains(it))
+            .flat_map(|it| it.items(ctx.sema.db))
             .for_each(|item| add_assoc_item(acc, item)),
         Qualified::TypeAnchor { trait_: Some(trait_), .. } => {
+            // Don't filter excluded traits here, user requested this specific trait.
             trait_.items(ctx.sema.db).into_iter().for_each(|item| add_assoc_item(acc, item))
         }
         Qualified::TypeAnchor { ty: Some(ty), trait_: None } => {
@@ -64,9 +105,14 @@ pub(crate) fn complete_expr_path(
                 acc.add_enum_variants(ctx, path_ctx, e);
             }
 
-            ctx.iterate_path_candidates(ty, |item| {
-                add_assoc_item(acc, item);
-            });
+            ty.iterate_path_candidates_split_inherent(
+                ctx.db,
+                &ctx.scope,
+                &ctx.traits_in_scope(),
+                Some(ctx.module),
+                None,
+                PathCallback { ctx, acc, add_assoc_item, seen: FxHashSet::default() },
+            );
 
             // Iterate assoc types separately
             ty.iterate_assoc_items(ctx.db, ctx.krate, |item| {
@@ -121,9 +167,14 @@ pub(crate) fn complete_expr_path(
                     // XXX: For parity with Rust bug #22519, this does not complete Ty::AssocType.
                     // (where AssocType is defined on a trait, not an inherent impl)
 
-                    ctx.iterate_path_candidates(&ty, |item| {
-                        add_assoc_item(acc, item);
-                    });
+                    ty.iterate_path_candidates_split_inherent(
+                        ctx.db,
+                        &ctx.scope,
+                        &ctx.traits_in_scope(),
+                        Some(ctx.module),
+                        None,
+                        PathCallback { ctx, acc, add_assoc_item, seen: FxHashSet::default() },
+                    );
 
                     // Iterate assoc types separately
                     ty.iterate_assoc_items(ctx.db, ctx.krate, |item| {
@@ -134,6 +185,7 @@ pub(crate) fn complete_expr_path(
                     });
                 }
                 hir::PathResolution::Def(hir::ModuleDef::Trait(t)) => {
+                    // Don't filter excluded traits here, user requested this specific trait.
                     // Handles `Trait::assoc` as well as `<Ty as Trait>::assoc`.
                     for item in t.items(ctx.db) {
                         add_assoc_item(acc, item);
@@ -151,9 +203,14 @@ pub(crate) fn complete_expr_path(
                         acc.add_enum_variants(ctx, path_ctx, e);
                     }
 
-                    ctx.iterate_path_candidates(&ty, |item| {
-                        add_assoc_item(acc, item);
-                    });
+                    ty.iterate_path_candidates_split_inherent(
+                        ctx.db,
+                        &ctx.scope,
+                        &ctx.traits_in_scope(),
+                        Some(ctx.module),
+                        None,
+                        PathCallback { ctx, acc, add_assoc_item, seen: FxHashSet::default() },
+                    );
                 }
                 _ => (),
             }
@@ -236,9 +293,17 @@ pub(crate) fn complete_expr_path(
                         [..] => acc.add_path_resolution(ctx, path_ctx, name, def, doc_aliases),
                     }
                 }
+                // synthetic names currently leak out as we lack synthetic hygiene, so filter them
+                // out here
+                ScopeDef::Local(_) => {
+                    if !name.as_str().starts_with('<') {
+                        acc.add_path_resolution(ctx, path_ctx, name, def, doc_aliases)
+                    }
+                }
                 _ if scope_def_applicable(def) => {
                     acc.add_path_resolution(ctx, path_ctx, name, def, doc_aliases)
                 }
+
                 _ => (),
             });
 
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs
index 847fa4cf889..bcfda928c4d 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs
@@ -46,7 +46,7 @@ pub(crate) fn complete_extern_abi(
     ctx: &CompletionContext<'_>,
     expanded: &ast::String,
 ) -> Option<()> {
-    if !expanded.syntax().parent().map_or(false, |it| ast::Abi::can_cast(it.kind())) {
+    if !expanded.syntax().parent().is_some_and(|it| ast::Abi::can_cast(it.kind())) {
         return None;
     }
     let abi_str = expanded;
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs
index 2a6b310d3a2..3b2b2fd706e 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/flyimport.rs
@@ -8,6 +8,7 @@ use itertools::Itertools;
 use syntax::{ast, AstNode, SyntaxNode, ToSmolStr, T};
 
 use crate::{
+    config::AutoImportExclusionType,
     context::{
         CompletionContext, DotAccess, PathCompletionCtx, PathKind, PatternContext, Qualified,
         TypeLocation,
@@ -267,6 +268,19 @@ fn import_on_the_fly(
                 && !ctx.is_item_hidden(original_item)
                 && ctx.check_stability(original_item.attrs(ctx.db).as_deref())
         })
+        .filter(|import| {
+            let def = import.item_to_import.into_module_def();
+            if let Some(&kind) = ctx.exclude_flyimport.get(&def) {
+                if kind == AutoImportExclusionType::Always {
+                    return false;
+                }
+                let method_imported = import.item_to_import != import.original_item;
+                if method_imported {
+                    return false;
+                }
+            }
+            true
+        })
         .sorted_by(|a, b| {
             let key = |import_path| {
                 (
@@ -352,6 +366,24 @@ fn import_on_the_fly_method(
             !ctx.is_item_hidden(&import.item_to_import)
                 && !ctx.is_item_hidden(&import.original_item)
         })
+        .filter(|import| {
+            let def = import.item_to_import.into_module_def();
+            if let Some(&kind) = ctx.exclude_flyimport.get(&def) {
+                if kind == AutoImportExclusionType::Always {
+                    return false;
+                }
+                let method_imported = import.item_to_import != import.original_item;
+                if method_imported {
+                    return false;
+                }
+            }
+
+            if let ModuleDef::Trait(_) = import.item_to_import.into_module_def() {
+                !ctx.exclude_flyimport.contains_key(&def)
+            } else {
+                true
+            }
+        })
         .sorted_by(|a, b| {
             let key = |import_path| {
                 (
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs
index ee3b817ee8c..e86eaad4d0f 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/fn_param.rs
@@ -167,7 +167,7 @@ fn should_add_self_completions(
         return false;
     }
     match param_list.params().next() {
-        Some(first) => first.pat().map_or(false, |pat| pat.syntax().text_range().contains(cursor)),
+        Some(first) => first.pat().is_some_and(|pat| pat.syntax().text_range().contains(cursor)),
         None => true,
     }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/record.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/record.rs
index 117a5e3d935..d0c4c24d060 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/record.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/record.rs
@@ -93,7 +93,7 @@ pub(crate) fn add_default_update(
     let default_trait = ctx.famous_defs().core_default_Default();
     let impls_default_trait = default_trait
         .zip(ty.as_ref())
-        .map_or(false, |(default_trait, ty)| ty.original.impls_trait(ctx.db, default_trait, &[]));
+        .is_some_and(|(default_trait, ty)| ty.original.impls_trait(ctx.db, default_trait, &[]));
     if impls_default_trait {
         // FIXME: This should make use of scope_def like completions so we get all the other goodies
         // that is we should handle this like actually completing the default function
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs
index 45704549e60..9d62622add2 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs
@@ -101,7 +101,7 @@ pub(crate) fn complete_use_path(
                     ScopeDef::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(e))) => {
                         // exclude prelude enum
                         let is_builtin =
-                            res.krate(ctx.db).map_or(false, |krate| krate.is_builtin(ctx.db));
+                            res.krate(ctx.db).is_some_and(|krate| krate.is_builtin(ctx.db));
 
                         if !is_builtin {
                             let item = CompletionItem::new(
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/config.rs b/src/tools/rust-analyzer/crates/ide-completion/src/config.rs
index 1d05419c96d..8b1ce11e8a4 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/config.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/config.rs
@@ -10,7 +10,7 @@ use ide_db::{imports::insert_use::InsertUseConfig, SnippetCap};
 use crate::{snippet::Snippet, CompletionFieldsToResolve};
 
 #[derive(Clone, Debug, PartialEq, Eq)]
-pub struct CompletionConfig {
+pub struct CompletionConfig<'a> {
     pub enable_postfix_completions: bool,
     pub enable_imports_on_the_fly: bool,
     pub enable_self_on_the_fly: bool,
@@ -28,6 +28,14 @@ pub struct CompletionConfig {
     pub snippets: Vec<Snippet>,
     pub limit: Option<usize>,
     pub fields_to_resolve: CompletionFieldsToResolve,
+    pub exclude_flyimport: Vec<(String, AutoImportExclusionType)>,
+    pub exclude_traits: &'a [String],
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+pub enum AutoImportExclusionType {
+    Always,
+    Methods,
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
@@ -36,7 +44,7 @@ pub enum CallableSnippets {
     AddParentheses,
 }
 
-impl CompletionConfig {
+impl CompletionConfig<'_> {
     pub fn postfix_snippets(&self) -> impl Iterator<Item = (&str, &Snippet)> {
         self.snippets
             .iter()
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 f8d403122d1..3705e2c73d6 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
@@ -7,8 +7,8 @@ mod tests;
 use std::{iter, ops::ControlFlow};
 
 use hir::{
-    HasAttrs, Local, ModuleSource, Name, PathResolution, ScopeDef, Semantics, SemanticsScope,
-    Symbol, Type, TypeInfo,
+    HasAttrs, Local, ModPath, ModuleDef, ModuleSource, Name, PathResolution, ScopeDef, Semantics,
+    SemanticsScope, Symbol, Type, TypeInfo,
 };
 use ide_db::{
     base_db::SourceDatabase, famous_defs::FamousDefs, helpers::is_editable_crate, FilePosition,
@@ -22,6 +22,7 @@ use syntax::{
 };
 
 use crate::{
+    config::AutoImportExclusionType,
     context::analysis::{expand_and_analyze, AnalysisResult},
     CompletionConfig,
 };
@@ -429,7 +430,7 @@ pub(crate) struct CompletionContext<'a> {
     pub(crate) sema: Semantics<'a, RootDatabase>,
     pub(crate) scope: SemanticsScope<'a>,
     pub(crate) db: &'a RootDatabase,
-    pub(crate) config: &'a CompletionConfig,
+    pub(crate) config: &'a CompletionConfig<'a>,
     pub(crate) position: FilePosition,
 
     /// The token before the cursor, in the original file.
@@ -462,6 +463,17 @@ pub(crate) struct CompletionContext<'a> {
     /// Here depth will be 2
     pub(crate) depth_from_crate_root: usize,
 
+    /// Traits whose methods will be excluded from flyimport. Flyimport should not suggest
+    /// importing those traits.
+    ///
+    /// Note the trait *themselves* are not excluded, only their methods are.
+    pub(crate) exclude_flyimport: FxHashMap<ModuleDef, AutoImportExclusionType>,
+    /// Traits whose methods should always be excluded, even when in scope (compare `exclude_flyimport_traits`).
+    /// They will *not* be excluded, however, if they are available as a generic bound.
+    ///
+    /// Note the trait *themselves* are not excluded, only their methods are.
+    pub(crate) exclude_traits: FxHashSet<hir::Trait>,
+
     /// Whether and how to complete semicolon for unit-returning functions.
     pub(crate) complete_semicolon: CompleteSemicolon,
 }
@@ -670,7 +682,7 @@ impl<'a> CompletionContext<'a> {
     pub(crate) fn new(
         db: &'a RootDatabase,
         position @ FilePosition { file_id, offset }: FilePosition,
-        config: &'a CompletionConfig,
+        config: &'a CompletionConfig<'a>,
     ) -> Option<(CompletionContext<'a>, CompletionAnalysis)> {
         let _p = tracing::info_span!("CompletionContext::new").entered();
         let sema = Semantics::new(db);
@@ -742,17 +754,53 @@ impl<'a> CompletionContext<'a> {
         let mut locals = FxHashMap::default();
         scope.process_all_names(&mut |name, scope| {
             if let ScopeDef::Local(local) = scope {
+                // synthetic names currently leak out as we lack synthetic hygiene, so filter them
+                // out here
+                if name.as_str().starts_with('<') {
+                    return;
+                }
                 locals.insert(name, local);
             }
         });
 
         let depth_from_crate_root = iter::successors(Some(module), |m| m.parent(db))
-            // `BlockExpr` modules are not count as module depth
+            // `BlockExpr` modules do not count towards module depth
             .filter(|m| !matches!(m.definition_source(db).value, ModuleSource::BlockExpr(_)))
             .count()
             // exclude `m` itself
             .saturating_sub(1);
 
+        let exclude_traits: FxHashSet<_> = config
+            .exclude_traits
+            .iter()
+            .filter_map(|path| {
+                scope
+                    .resolve_mod_path(&ModPath::from_segments(
+                        hir::PathKind::Plain,
+                        path.split("::").map(Symbol::intern).map(Name::new_symbol_root),
+                    ))
+                    .find_map(|it| match it {
+                        hir::ItemInNs::Types(ModuleDef::Trait(t)) => Some(t),
+                        _ => None,
+                    })
+            })
+            .collect();
+
+        let mut exclude_flyimport: FxHashMap<_, _> = config
+            .exclude_flyimport
+            .iter()
+            .flat_map(|(path, kind)| {
+                scope
+                    .resolve_mod_path(&ModPath::from_segments(
+                        hir::PathKind::Plain,
+                        path.split("::").map(Symbol::intern).map(Name::new_symbol_root),
+                    ))
+                    .map(|it| (it.into_module_def(), *kind))
+            })
+            .collect();
+        exclude_flyimport
+            .extend(exclude_traits.iter().map(|&t| (t.into(), AutoImportExclusionType::Always)));
+
         let complete_semicolon = if config.add_semicolon_to_unit {
             let inside_closure_ret = token.parent_ancestors().try_for_each(|ancestor| {
                 match_ast! {
@@ -817,6 +865,8 @@ impl<'a> CompletionContext<'a> {
             qualifier_ctx,
             locals,
             depth_from_crate_root,
+            exclude_flyimport,
+            exclude_traits,
             complete_semicolon,
         };
         Some((ctx, analysis))
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
index 1c4cbb25b1f..acce62a041c 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
@@ -417,6 +417,15 @@ fn analyze(
         derive_ctx,
     } = expansion_result;
 
+    if original_token.kind() != self_token.kind()
+        // FIXME: This check can be removed once we use speculative database forking for completions
+        && !(original_token.kind().is_punct() || original_token.kind().is_trivia())
+        && !(SyntaxKind::is_any_identifier(original_token.kind())
+            && SyntaxKind::is_any_identifier(self_token.kind()))
+    {
+        return None;
+    }
+
     // Overwrite the path kind for derives
     if let Some((original_file, file_with_fake_ident, offset, origin_attr)) = derive_ctx {
         if let Some(ast::NameLike::NameRef(name_ref)) =
@@ -456,7 +465,7 @@ fn analyze(
                 && p.ancestors().any(|it| it.kind() == SyntaxKind::META)
             {
                 let colon_prefix = previous_non_trivia_token(self_token.clone())
-                    .map_or(false, |it| T![:] == it.kind());
+                    .is_some_and(|it| T![:] == it.kind());
 
                 CompletionAnalysis::UnexpandedAttrTT {
                     fake_attribute_under_caret: fake_ident_token
@@ -643,7 +652,7 @@ fn expected_type_and_name(
                 // match foo { $0 }
                 // match foo { ..., pat => $0 }
                 ast::MatchExpr(it) => {
-                    let on_arrow = previous_non_trivia_token(token.clone()).map_or(false, |it| T![=>] == it.kind());
+                    let on_arrow = previous_non_trivia_token(token.clone()).is_some_and(|it| T![=>] == it.kind());
 
                     let ty = if on_arrow {
                         // match foo { ..., pat => $0 }
@@ -780,7 +789,7 @@ fn classify_name_ref(
 
     if let Some(record_field) = ast::RecordExprField::for_field_name(&name_ref) {
         let dot_prefix = previous_non_trivia_token(name_ref.syntax().clone())
-            .map_or(false, |it| T![.] == it.kind());
+            .is_some_and(|it| T![.] == it.kind());
 
         return find_node_in_file_compensated(
             sema,
@@ -814,7 +823,7 @@ fn classify_name_ref(
                 let receiver_is_ambiguous_float_literal = match &receiver {
                     Some(ast::Expr::Literal(l)) => matches! {
                         l.kind(),
-                        ast::LiteralKind::FloatNumber { .. } if l.syntax().last_token().map_or(false, |it| it.text().ends_with('.'))
+                        ast::LiteralKind::FloatNumber { .. } if l.syntax().last_token().is_some_and(|it| it.text().ends_with('.'))
                     },
                     _ => false,
                 };
@@ -846,7 +855,7 @@ fn classify_name_ref(
                 let receiver = find_opt_node_in_file(original_file, method.receiver());
                 let kind = NameRefKind::DotAccess(DotAccess {
                     receiver_ty: receiver.as_ref().and_then(|it| sema.type_of_expr(it)),
-                    kind: DotAccessKind::Method { has_parens: method.arg_list().map_or(false, |it| it.l_paren_token().is_some()) },
+                    kind: DotAccessKind::Method { has_parens: method.arg_list().is_some_and(|it| it.l_paren_token().is_some()) },
                     receiver,
                     ctx: DotAccessExprCtx { in_block_expr: is_in_block(method.syntax()), in_breakable: is_in_breakable(method.syntax()) }
                 });
@@ -1193,13 +1202,13 @@ fn classify_name_ref(
         let incomplete_let = it
             .parent()
             .and_then(ast::LetStmt::cast)
-            .map_or(false, |it| it.semicolon_token().is_none());
+            .is_some_and(|it| it.semicolon_token().is_none());
         let impl_ = fetch_immediate_impl(sema, original_file, expr.syntax());
 
         let in_match_guard = match it.parent().and_then(ast::MatchArm::cast) {
             Some(arm) => arm
                 .fat_arrow_token()
-                .map_or(true, |arrow| it.text_range().start() < arrow.text_range().start()),
+                .is_none_or(|arrow| it.text_range().start() < arrow.text_range().start()),
             None => false,
         };
 
@@ -1329,7 +1338,7 @@ fn classify_name_ref(
                         }
                     }
 
-                    path_ctx.has_call_parens = it.syntax().parent().map_or(false, |it| ast::CallExpr::can_cast(it.kind()));
+                    path_ctx.has_call_parens = it.syntax().parent().is_some_and(|it| ast::CallExpr::can_cast(it.kind()));
 
                     make_path_kind_expr(it.into())
                 },
@@ -1358,7 +1367,7 @@ fn classify_name_ref(
                         match parent {
                             ast::PathType(it) => make_path_kind_type(it.into()),
                             ast::PathExpr(it) => {
-                                path_ctx.has_call_parens = it.syntax().parent().map_or(false, |it| ast::CallExpr::can_cast(it.kind()));
+                                path_ctx.has_call_parens = it.syntax().parent().is_some_and(|it| ast::CallExpr::can_cast(it.kind()));
 
                                 make_path_kind_expr(it.into())
                             },
@@ -1612,8 +1621,7 @@ fn pattern_context_for(
             &pat,
             ast::Pat::IdentPat(it)
                 if it.syntax()
-                .parent()
-                .map_or(false, |node| {
+                .parent().is_some_and(|node| {
                     let kind = node.kind();
                     ast::LetStmt::can_cast(kind) || ast::Param::can_cast(kind)
                 })
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 9608eed99d8..b91f915619d 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
@@ -631,7 +631,7 @@ impl Builder {
         self.set_documentation(Some(docs))
     }
     pub(crate) fn set_documentation(&mut self, docs: Option<Documentation>) -> &mut Builder {
-        self.documentation = docs.map(Into::into);
+        self.documentation = docs;
         self
     }
     pub(crate) fn set_deprecated(&mut self, deprecated: bool) -> &mut Builder {
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs
index 14f42b40055..ca6c9ad9f08 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs
@@ -31,7 +31,7 @@ use crate::{
 };
 
 pub use crate::{
-    config::{CallableSnippets, CompletionConfig},
+    config::{AutoImportExclusionType, CallableSnippets, CompletionConfig},
     item::{
         CompletionItem, CompletionItemKind, CompletionRelevance, CompletionRelevancePostfixMatch,
         CompletionRelevanceReturnType, CompletionRelevanceTypeMatch,
@@ -184,7 +184,7 @@ impl CompletionFieldsToResolve {
 /// analysis.
 pub fn completions(
     db: &RootDatabase,
-    config: &CompletionConfig,
+    config: &CompletionConfig<'_>,
     position: FilePosition,
     trigger_character: Option<char>,
 ) -> Option<Vec<CompletionItem>> {
@@ -269,7 +269,7 @@ pub fn completions(
 /// This is used for import insertion done via completions like flyimport and custom user snippets.
 pub fn resolve_completion_edits(
     db: &RootDatabase,
-    config: &CompletionConfig,
+    config: &CompletionConfig<'_>,
     FilePosition { file_id, offset }: FilePosition,
     imports: impl IntoIterator<Item = (String, String)>,
 ) -> Option<Vec<TextEdit>> {
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 baa30b28630..c239ca512da 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
@@ -86,11 +86,7 @@ impl<'a> RenderContext<'a> {
 
     fn is_immediately_after_macro_bang(&self) -> bool {
         self.completion.token.kind() == SyntaxKind::BANG
-            && self
-                .completion
-                .token
-                .parent()
-                .map_or(false, |it| it.kind() == SyntaxKind::MACRO_CALL)
+            && self.completion.token.parent().is_some_and(|it| it.kind() == SyntaxKind::MACRO_CALL)
     }
 
     fn is_deprecated(&self, def: impl HasAttrs) -> bool {
@@ -636,7 +632,7 @@ fn compute_type_match(
 }
 
 fn compute_exact_name_match(ctx: &CompletionContext<'_>, completion_name: &str) -> bool {
-    ctx.expected_name.as_ref().map_or(false, |name| name.text() == completion_name)
+    ctx.expected_name.as_ref().is_some_and(|name| name.text() == completion_name)
 }
 
 fn compute_ref_match(
@@ -778,7 +774,7 @@ mod tests {
                     relevance.postfix_match == Some(CompletionRelevancePostfixMatch::Exact),
                     "snippet",
                 ),
-                (relevance.trait_.map_or(false, |it| it.is_op_method), "op_method"),
+                (relevance.trait_.is_some_and(|it| it.is_op_method), "op_method"),
                 (relevance.requires_import, "requires_import"),
             ]
             .into_iter()
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs b/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs
index 5265aa8515b..04bb178c658 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/snippet.rs
@@ -100,9 +100,9 @@
 // }
 // ----
 
+use hir::{ModPath, Name, Symbol};
 use ide_db::imports::import_assets::LocatedImport;
 use itertools::Itertools;
-use syntax::{ast, AstNode, GreenNode, SyntaxNode};
 
 use crate::context::CompletionContext;
 
@@ -123,10 +123,7 @@ pub struct Snippet {
     pub scope: SnippetScope,
     pub description: Option<Box<str>>,
     snippet: String,
-    // These are `ast::Path`'s but due to SyntaxNodes not being Send we store these
-    // and reconstruct them on demand instead. This is cheaper than reparsing them
-    // from strings
-    requires: Box<[GreenNode]>,
+    requires: Box<[ModPath]>,
 }
 
 impl Snippet {
@@ -143,7 +140,6 @@ impl Snippet {
         }
         let (requires, snippet, description) = validate_snippet(snippet, description, requires)?;
         Some(Snippet {
-            // Box::into doesn't work as that has a Copy bound 😒
             postfix_triggers: postfix_triggers.iter().map(String::as_str).map(Into::into).collect(),
             prefix_triggers: prefix_triggers.iter().map(String::as_str).map(Into::into).collect(),
             scope,
@@ -167,15 +163,11 @@ impl Snippet {
     }
 }
 
-fn import_edits(ctx: &CompletionContext<'_>, requires: &[GreenNode]) -> Option<Vec<LocatedImport>> {
+fn import_edits(ctx: &CompletionContext<'_>, requires: &[ModPath]) -> Option<Vec<LocatedImport>> {
     let import_cfg = ctx.config.import_path_config();
 
-    let resolve = |import: &GreenNode| {
-        let path = ast::Path::cast(SyntaxNode::new_root(import.clone()))?;
-        let item = match ctx.scope.speculative_resolve(&path)? {
-            hir::PathResolution::Def(def) => def.into(),
-            _ => return None,
-        };
+    let resolve = |import| {
+        let item = ctx.scope.resolve_mod_path(import).next()?;
         let path = ctx.module.find_use_path(
             ctx.db,
             item,
@@ -198,19 +190,14 @@ fn validate_snippet(
     snippet: &[String],
     description: &str,
     requires: &[String],
-) -> Option<(Box<[GreenNode]>, String, Option<Box<str>>)> {
+) -> Option<(Box<[ModPath]>, String, Option<Box<str>>)> {
     let mut imports = Vec::with_capacity(requires.len());
     for path in requires.iter() {
-        let use_path =
-            ast::SourceFile::parse(&format!("use {path};"), syntax::Edition::CURRENT_FIXME)
-                .syntax_node()
-                .descendants()
-                .find_map(ast::Path::cast)?;
-        if use_path.syntax().text() != path.as_str() {
-            return None;
-        }
-        let green = use_path.syntax().green().into_owned();
-        imports.push(green);
+        let use_path = ModPath::from_segments(
+            hir::PathKind::Plain,
+            path.split("::").map(Symbol::intern).map(Name::new_symbol_root),
+        );
+        imports.push(use_path);
     }
     let snippet = snippet.iter().join("\n");
     let description = (!description.is_empty())
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs
index e01097a9105..1815f340532 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests.rs
@@ -61,7 +61,7 @@ fn function() {}
 union Union { field: i32 }
 "#;
 
-pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig {
+pub(crate) const TEST_CONFIG: CompletionConfig<'_> = CompletionConfig {
     enable_postfix_completions: true,
     enable_imports_on_the_fly: true,
     enable_self_on_the_fly: true,
@@ -85,6 +85,8 @@ pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig {
     snippets: Vec::new(),
     limit: None,
     fields_to_resolve: CompletionFieldsToResolve::empty(),
+    exclude_flyimport: vec![],
+    exclude_traits: &[],
 };
 
 pub(crate) fn completion_list(ra_fixture: &str) -> String {
@@ -109,7 +111,7 @@ pub(crate) fn completion_list_with_trigger_character(
 }
 
 fn completion_list_with_config_raw(
-    config: CompletionConfig,
+    config: CompletionConfig<'_>,
     ra_fixture: &str,
     include_keywords: bool,
     trigger_character: Option<char>,
@@ -132,7 +134,7 @@ fn completion_list_with_config_raw(
 }
 
 fn completion_list_with_config(
-    config: CompletionConfig,
+    config: CompletionConfig<'_>,
     ra_fixture: &str,
     include_keywords: bool,
     trigger_character: Option<char>,
@@ -161,7 +163,7 @@ pub(crate) fn do_completion(code: &str, kind: CompletionItemKind) -> Vec<Complet
 }
 
 pub(crate) fn do_completion_with_config(
-    config: CompletionConfig,
+    config: CompletionConfig<'_>,
     code: &str,
     kind: CompletionItemKind,
 ) -> Vec<CompletionItem> {
@@ -220,7 +222,7 @@ pub(crate) fn check_edit(what: &str, ra_fixture_before: &str, ra_fixture_after:
 
 #[track_caller]
 pub(crate) fn check_edit_with_config(
-    config: CompletionConfig,
+    config: CompletionConfig<'_>,
     what: &str,
     ra_fixture_before: &str,
     ra_fixture_after: &str,
@@ -257,7 +259,7 @@ fn check_empty(ra_fixture: &str, expect: Expect) {
 }
 
 pub(crate) fn get_all_items(
-    config: CompletionConfig,
+    config: CompletionConfig<'_>,
     code: &str,
     trigger_character: Option<char>,
 ) -> Vec<CompletionItem> {
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs
index acafa6518f6..ebf35820570 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/attribute.rs
@@ -713,6 +713,28 @@ struct Foo;
     );
 }
 
+#[test]
+fn issue_17479() {
+    check(
+        r#"
+//- proc_macros: issue_17479
+fn main() {
+    proc_macros::issue_17479!("te$0");
+}
+"#,
+        expect![""],
+    );
+    check(
+        r#"
+//- proc_macros: issue_17479
+fn main() {
+    proc_macros::issue_17479!("$0");
+}
+"#,
+        expect![""],
+    )
+}
+
 mod cfg {
     use super::*;
 
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 ea1b7ad7871..30466148686 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
@@ -1,13 +1,30 @@
 //! Completion tests for expressions.
 use expect_test::{expect, Expect};
 
-use crate::tests::{check_edit, check_empty, completion_list, BASE_ITEMS_FIXTURE};
+use crate::{
+    config::AutoImportExclusionType,
+    tests::{
+        check_edit, check_empty, completion_list, completion_list_with_config, BASE_ITEMS_FIXTURE,
+        TEST_CONFIG,
+    },
+    CompletionConfig,
+};
 
 fn check(ra_fixture: &str, expect: Expect) {
     let actual = completion_list(&format!("{BASE_ITEMS_FIXTURE}{ra_fixture}"));
     expect.assert_eq(&actual)
 }
 
+fn check_with_config(config: CompletionConfig<'_>, ra_fixture: &str, expect: Expect) {
+    let actual = completion_list_with_config(
+        config,
+        &format!("{BASE_ITEMS_FIXTURE}{ra_fixture}"),
+        true,
+        None,
+    );
+    expect.assert_eq(&actual)
+}
+
 #[test]
 fn complete_literal_struct_with_a_private_field() {
     // `FooDesc.bar` is private, the completion should not be triggered.
@@ -1390,3 +1407,453 @@ fn main() {
         "#]],
     );
 }
+
+#[test]
+fn excluded_trait_method_is_excluded() {
+    check_with_config(
+        CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
+        r#"
+trait ExcludedTrait {
+    fn foo(&self) {}
+    fn bar(&self) {}
+    fn baz(&self) {}
+}
+
+impl<T> ExcludedTrait for T {}
+
+struct Foo;
+impl Foo {
+    fn inherent(&self) {}
+}
+
+fn foo() {
+    Foo.$0
+}
+        "#,
+        expect![[r#"
+            me bar() (as ExcludedTrait) fn(&self)
+            me baz() (as ExcludedTrait) fn(&self)
+            me foo() (as ExcludedTrait) fn(&self)
+            me inherent()               fn(&self)
+            sn box                 Box::new(expr)
+            sn call                function(expr)
+            sn dbg                     dbg!(expr)
+            sn dbgr                   dbg!(&expr)
+            sn deref                        *expr
+            sn let                            let
+            sn letm                       let mut
+            sn match                match expr {}
+            sn ref                          &expr
+            sn refm                     &mut expr
+            sn return                 return expr
+            sn unsafe                   unsafe {}
+        "#]],
+    );
+}
+
+#[test]
+fn excluded_trait_not_excluded_when_inherent() {
+    check_with_config(
+        CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
+        r#"
+trait ExcludedTrait {
+    fn foo(&self) {}
+    fn bar(&self) {}
+    fn baz(&self) {}
+}
+
+impl<T> ExcludedTrait for T {}
+
+fn foo(v: &dyn ExcludedTrait) {
+    v.$0
+}
+        "#,
+        expect![[r#"
+            me bar() (as ExcludedTrait) fn(&self)
+            me baz() (as ExcludedTrait) fn(&self)
+            me foo() (as ExcludedTrait) fn(&self)
+            sn box                 Box::new(expr)
+            sn call                function(expr)
+            sn dbg                     dbg!(expr)
+            sn dbgr                   dbg!(&expr)
+            sn deref                        *expr
+            sn let                            let
+            sn letm                       let mut
+            sn match                match expr {}
+            sn ref                          &expr
+            sn refm                     &mut expr
+            sn return                 return expr
+            sn unsafe                   unsafe {}
+        "#]],
+    );
+    check_with_config(
+        CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
+        r#"
+trait ExcludedTrait {
+    fn foo(&self) {}
+    fn bar(&self) {}
+    fn baz(&self) {}
+}
+
+impl<T> ExcludedTrait for T {}
+
+fn foo(v: impl ExcludedTrait) {
+    v.$0
+}
+        "#,
+        expect![[r#"
+            me bar() (as ExcludedTrait) fn(&self)
+            me baz() (as ExcludedTrait) fn(&self)
+            me foo() (as ExcludedTrait) fn(&self)
+            sn box                 Box::new(expr)
+            sn call                function(expr)
+            sn dbg                     dbg!(expr)
+            sn dbgr                   dbg!(&expr)
+            sn deref                        *expr
+            sn let                            let
+            sn letm                       let mut
+            sn match                match expr {}
+            sn ref                          &expr
+            sn refm                     &mut expr
+            sn return                 return expr
+            sn unsafe                   unsafe {}
+        "#]],
+    );
+    check_with_config(
+        CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
+        r#"
+trait ExcludedTrait {
+    fn foo(&self) {}
+    fn bar(&self) {}
+    fn baz(&self) {}
+}
+
+impl<T> ExcludedTrait for T {}
+
+fn foo<T: ExcludedTrait>(v: T) {
+    v.$0
+}
+        "#,
+        expect![[r#"
+            me bar() (as ExcludedTrait) fn(&self)
+            me baz() (as ExcludedTrait) fn(&self)
+            me foo() (as ExcludedTrait) fn(&self)
+            sn box                 Box::new(expr)
+            sn call                function(expr)
+            sn dbg                     dbg!(expr)
+            sn dbgr                   dbg!(&expr)
+            sn deref                        *expr
+            sn let                            let
+            sn letm                       let mut
+            sn match                match expr {}
+            sn ref                          &expr
+            sn refm                     &mut expr
+            sn return                 return expr
+            sn unsafe                   unsafe {}
+        "#]],
+    );
+}
+
+#[test]
+fn excluded_trait_method_is_excluded_from_flyimport() {
+    check_with_config(
+        CompletionConfig {
+            exclude_traits: &["test::module2::ExcludedTrait".to_owned()],
+            ..TEST_CONFIG
+        },
+        r#"
+mod module2 {
+    pub trait ExcludedTrait {
+        fn foo(&self) {}
+        fn bar(&self) {}
+        fn baz(&self) {}
+    }
+
+    impl<T> ExcludedTrait for T {}
+}
+
+struct Foo;
+impl Foo {
+    fn inherent(&self) {}
+}
+
+fn foo() {
+    Foo.$0
+}
+        "#,
+        expect![[r#"
+            me bar() (use module2::ExcludedTrait) fn(&self)
+            me baz() (use module2::ExcludedTrait) fn(&self)
+            me foo() (use module2::ExcludedTrait) fn(&self)
+            me inherent()                         fn(&self)
+            sn box                           Box::new(expr)
+            sn call                          function(expr)
+            sn dbg                               dbg!(expr)
+            sn dbgr                             dbg!(&expr)
+            sn deref                                  *expr
+            sn let                                      let
+            sn letm                                 let mut
+            sn match                          match expr {}
+            sn ref                                    &expr
+            sn refm                               &mut expr
+            sn return                           return expr
+            sn unsafe                             unsafe {}
+        "#]],
+    );
+}
+
+#[test]
+fn flyimport_excluded_trait_method_is_excluded_from_flyimport() {
+    check_with_config(
+        CompletionConfig {
+            exclude_flyimport: vec![(
+                "test::module2::ExcludedTrait".to_owned(),
+                AutoImportExclusionType::Methods,
+            )],
+            ..TEST_CONFIG
+        },
+        r#"
+mod module2 {
+    pub trait ExcludedTrait {
+        fn foo(&self) {}
+        fn bar(&self) {}
+        fn baz(&self) {}
+    }
+
+    impl<T> ExcludedTrait for T {}
+}
+
+struct Foo;
+impl Foo {
+    fn inherent(&self) {}
+}
+
+fn foo() {
+    Foo.$0
+}
+        "#,
+        expect![[r#"
+            me bar() (use module2::ExcludedTrait) fn(&self)
+            me baz() (use module2::ExcludedTrait) fn(&self)
+            me foo() (use module2::ExcludedTrait) fn(&self)
+            me inherent()                         fn(&self)
+            sn box                           Box::new(expr)
+            sn call                          function(expr)
+            sn dbg                               dbg!(expr)
+            sn dbgr                             dbg!(&expr)
+            sn deref                                  *expr
+            sn let                                      let
+            sn letm                                 let mut
+            sn match                          match expr {}
+            sn ref                                    &expr
+            sn refm                               &mut expr
+            sn return                           return expr
+            sn unsafe                             unsafe {}
+        "#]],
+    );
+}
+
+#[test]
+fn excluded_trait_method_is_excluded_from_path_completion() {
+    check_with_config(
+        CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
+        r#"
+pub trait ExcludedTrait {
+    fn foo(&self) {}
+    fn bar(&self) {}
+    fn baz(&self) {}
+}
+
+impl<T> ExcludedTrait for T {}
+
+struct Foo;
+impl Foo {
+    fn inherent(&self) {}
+}
+
+fn foo() {
+    Foo::$0
+}
+        "#,
+        expect![[r#"
+            me bar(…) (as ExcludedTrait) fn(&self)
+            me baz(…) (as ExcludedTrait) fn(&self)
+            me foo(…) (as ExcludedTrait) fn(&self)
+            me inherent(…)               fn(&self)
+        "#]],
+    );
+}
+
+#[test]
+fn excluded_trait_method_is_not_excluded_when_trait_is_specified() {
+    check_with_config(
+        CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
+        r#"
+pub trait ExcludedTrait {
+    fn foo(&self) {}
+    fn bar(&self) {}
+    fn baz(&self) {}
+}
+
+impl<T> ExcludedTrait for T {}
+
+struct Foo;
+impl Foo {
+    fn inherent(&self) {}
+}
+
+fn foo() {
+    ExcludedTrait::$0
+}
+        "#,
+        expect![[r#"
+                me bar(…) (as ExcludedTrait) fn(&self)
+                me baz(…) (as ExcludedTrait) fn(&self)
+                me foo(…) (as ExcludedTrait) fn(&self)
+            "#]],
+    );
+    check_with_config(
+        CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
+        r#"
+pub trait ExcludedTrait {
+    fn foo(&self) {}
+    fn bar(&self) {}
+    fn baz(&self) {}
+}
+
+impl<T> ExcludedTrait for T {}
+
+struct Foo;
+impl Foo {
+    fn inherent(&self) {}
+}
+
+fn foo() {
+    <Foo as ExcludedTrait>::$0
+}
+        "#,
+        expect![[r#"
+                me bar(…) (as ExcludedTrait) fn(&self)
+                me baz(…) (as ExcludedTrait) fn(&self)
+                me foo(…) (as ExcludedTrait) fn(&self)
+            "#]],
+    );
+}
+
+#[test]
+fn excluded_trait_not_excluded_when_inherent_path() {
+    check_with_config(
+        CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
+        r#"
+trait ExcludedTrait {
+    fn foo(&self) {}
+    fn bar(&self) {}
+    fn baz(&self) {}
+}
+
+impl<T> ExcludedTrait for T {}
+
+fn foo() {
+    <dyn ExcludedTrait>::$0
+}
+        "#,
+        expect![[r#"
+            me bar(…) (as ExcludedTrait) fn(&self)
+            me baz(…) (as ExcludedTrait) fn(&self)
+            me foo(…) (as ExcludedTrait) fn(&self)
+        "#]],
+    );
+    check_with_config(
+        CompletionConfig { exclude_traits: &["test::ExcludedTrait".to_owned()], ..TEST_CONFIG },
+        r#"
+trait ExcludedTrait {
+    fn foo(&self) {}
+    fn bar(&self) {}
+    fn baz(&self) {}
+}
+
+impl<T> ExcludedTrait for T {}
+
+fn foo<T: ExcludedTrait>() {
+    T::$0
+}
+        "#,
+        expect![[r#"
+            me bar(…) (as ExcludedTrait) fn(&self)
+            me baz(…) (as ExcludedTrait) fn(&self)
+            me foo(…) (as ExcludedTrait) fn(&self)
+        "#]],
+    );
+}
+
+#[test]
+fn hide_ragennew_synthetic_identifiers() {
+    check_empty(
+        r#"
+//- minicore: iterator
+fn bar() {
+    for i in [0; 10] {
+        r$0
+    }
+}
+        "#,
+        expect![[r#"
+            en Option                             Option<{unknown}>
+            en Result                  Result<{unknown}, {unknown}>
+            fn bar()                                           fn()
+            lc i                                                i32
+            ma const_format_args!(…) macro_rules! const_format_args
+            ma format_args!(…)             macro_rules! format_args
+            ma format_args_nl!(…)       macro_rules! format_args_nl
+            ma panic!(…)                         macro_rules! panic
+            ma print!(…)                         macro_rules! print
+            md core
+            md result (use core::result)
+            md rust_2015 (use core::prelude::rust_2015)
+            md rust_2018 (use core::prelude::rust_2018)
+            md rust_2021 (use core::prelude::rust_2021)
+            tt Clone
+            tt Copy
+            tt IntoIterator
+            tt Iterator
+            ta Result (use core::fmt::Result)
+            ev Err(…)                                        Err(E)
+            ev None                                            None
+            ev Ok(…)                                          Ok(T)
+            ev Some(…)                                      Some(T)
+            bt u32                                              u32
+            kw async
+            kw break
+            kw const
+            kw continue
+            kw crate::
+            kw enum
+            kw extern
+            kw false
+            kw fn
+            kw for
+            kw if
+            kw if let
+            kw impl
+            kw let
+            kw loop
+            kw match
+            kw mod
+            kw return
+            kw self::
+            kw static
+            kw struct
+            kw trait
+            kw true
+            kw type
+            kw union
+            kw unsafe
+            kw use
+            kw while
+            kw while let
+            sn macro_rules
+            sn pd
+            sn ppd
+        "#]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs
index 447dbc998b5..d413977f7c8 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs
@@ -3,10 +3,14 @@ use expect_test::{expect, Expect};
 use crate::{
     context::{CompletionAnalysis, NameContext, NameKind, NameRefKind},
     tests::{check_edit, check_edit_with_config, TEST_CONFIG},
+    CompletionConfig,
 };
 
 fn check(ra_fixture: &str, expect: Expect) {
-    let config = TEST_CONFIG;
+    check_with_config(TEST_CONFIG, ra_fixture, expect);
+}
+
+fn check_with_config(config: CompletionConfig<'_>, ra_fixture: &str, expect: Expect) {
     let (db, position) = crate::tests::position(ra_fixture);
     let (ctx, analysis) = crate::context::CompletionContext::new(&db, position, &config).unwrap();
 
@@ -1762,3 +1766,31 @@ fn function() {
         expect![""],
     );
 }
+
+#[test]
+fn excluded_trait_item_included_when_exact_match() {
+    check_with_config(
+        CompletionConfig {
+            exclude_traits: &["test::module2::ExcludedTrait".to_owned()],
+            ..TEST_CONFIG
+        },
+        r#"
+mod module2 {
+    pub trait ExcludedTrait {
+        fn foo(&self) {}
+        fn bar(&self) {}
+        fn baz(&self) {}
+    }
+
+    impl<T> ExcludedTrait for T {}
+}
+
+fn foo() {
+    true.foo$0
+}
+        "#,
+        expect![[r#"
+            me foo() (use module2::ExcludedTrait) fn(&self)
+        "#]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs
index f34f3d0fc2f..79561a0419f 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/item.rs
@@ -241,3 +241,75 @@ impl Copy for S where $0
 "#,
     );
 }
+
+#[test]
+fn test_is_not_considered_macro() {
+    check(
+        r#"
+#[rustc_builtin]
+pub macro test($item:item) {
+    /* compiler built-in */
+}
+
+macro_rules! expand_to_test {
+    ( $i:ident ) => {
+        #[test]
+        fn foo() { $i; }
+    };
+}
+
+fn bar() {
+    let value = 5;
+    expand_to_test!(v$0);
+}
+    "#,
+        expect![[r#"
+            ct CONST                                     Unit
+            en Enum                                      Enum
+            fn bar()                                     fn()
+            fn foo()                                     fn()
+            fn function()                                fn()
+            ma expand_to_test!(…) macro_rules! expand_to_test
+            ma makro!(…)                   macro_rules! makro
+            ma test!(…)                            macro test
+            md module
+            sc STATIC                                    Unit
+            st Record                                  Record
+            st Tuple                                    Tuple
+            st Unit                                      Unit
+            un Union                                    Union
+            ev TupleV(…)                          TupleV(u32)
+            bt u32                                        u32
+            kw async
+            kw const
+            kw crate::
+            kw enum
+            kw extern
+            kw false
+            kw fn
+            kw for
+            kw if
+            kw if let
+            kw impl
+            kw let
+            kw loop
+            kw match
+            kw mod
+            kw return
+            kw self::
+            kw static
+            kw struct
+            kw trait
+            kw true
+            kw type
+            kw union
+            kw unsafe
+            kw use
+            kw while
+            kw while let
+            sn macro_rules
+            sn pd
+            sn ppd
+        "#]],
+    );
+}
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 388af48c68b..6cfb2231a99 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
@@ -1345,7 +1345,7 @@ struct Foo<T: PartialOrd
 }
 
 fn check_signatures(src: &str, kind: CompletionItemKind, reduced: Expect, full: Expect) {
-    const FULL_SIGNATURES_CONFIG: crate::CompletionConfig = {
+    const FULL_SIGNATURES_CONFIG: crate::CompletionConfig<'_> = {
         let mut x = TEST_CONFIG;
         x.full_function_signatures = true;
         x
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs b/src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs
index 42a80d63b1a..7482491fc63 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/active_parameter.rs
@@ -48,7 +48,7 @@ pub fn callable_for_token(
     let parent = token.parent()?;
     let calling_node = parent.ancestors().filter_map(ast::CallableExpr::cast).find(|it| {
         it.arg_list()
-            .map_or(false, |it| it.syntax().text_range().contains(token.text_range().start()))
+            .is_some_and(|it| it.syntax().text_range().contains(token.text_range().start()))
     })?;
 
     callable_for_node(sema, &calling_node, &token)
@@ -136,7 +136,7 @@ pub fn generic_def_for_node(
     let first_arg_is_non_lifetime = generic_arg_list
         .generic_args()
         .next()
-        .map_or(false, |arg| !matches!(arg, ast::GenericArg::LifetimeArg(_)));
+        .is_some_and(|arg| !matches!(arg, ast::GenericArg::LifetimeArg(_)));
 
     Some((def, active_param, first_arg_is_non_lifetime, variant))
 }
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs
index 932ca373020..2d30bb41273 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs
@@ -13,9 +13,10 @@ use either::Either;
 use hir::{
     Adt, AsAssocItem, AsExternAssocItem, AssocItem, AttributeTemplate, BuiltinAttr, BuiltinType,
     Const, Crate, DefWithBody, DeriveHelper, DocLinkDef, ExternAssocItem, ExternCrateDecl, Field,
-    Function, GenericParam, HasVisibility, HirDisplay, Impl, InlineAsmOperand, Label, Local, Macro,
-    Module, ModuleDef, Name, PathResolution, Semantics, Static, StaticLifetime, Struct, ToolModule,
-    Trait, TraitAlias, TupleField, TypeAlias, Variant, VariantDef, Visibility,
+    Function, GenericDef, GenericParam, GenericSubstitution, HasContainer, HasVisibility,
+    HirDisplay, Impl, InlineAsmOperand, ItemContainer, Label, Local, Macro, Module, ModuleDef,
+    Name, PathResolution, Semantics, Static, StaticLifetime, Struct, ToolModule, Trait, TraitAlias,
+    TupleField, TypeAlias, Variant, VariantDef, Visibility,
 };
 use span::Edition;
 use stdx::{format_to, impl_from};
@@ -96,9 +97,39 @@ impl Definition {
     }
 
     pub fn enclosing_definition(&self, db: &RootDatabase) -> Option<Definition> {
+        fn container_to_definition(container: ItemContainer) -> Option<Definition> {
+            match container {
+                ItemContainer::Trait(it) => Some(it.into()),
+                ItemContainer::Impl(it) => Some(it.into()),
+                ItemContainer::Module(it) => Some(it.into()),
+                ItemContainer::ExternBlock() | ItemContainer::Crate(_) => None,
+            }
+        }
         match self {
+            Definition::Macro(it) => Some(it.module(db).into()),
+            Definition::Module(it) => it.parent(db).map(Definition::Module),
+            Definition::Field(it) => Some(it.parent_def(db).into()),
+            Definition::Function(it) => container_to_definition(it.container(db)),
+            Definition::Adt(it) => Some(it.module(db).into()),
+            Definition::Const(it) => container_to_definition(it.container(db)),
+            Definition::Static(it) => container_to_definition(it.container(db)),
+            Definition::Trait(it) => container_to_definition(it.container(db)),
+            Definition::TraitAlias(it) => container_to_definition(it.container(db)),
+            Definition::TypeAlias(it) => container_to_definition(it.container(db)),
+            Definition::Variant(it) => Some(Adt::Enum(it.parent_enum(db)).into()),
+            Definition::SelfType(it) => Some(it.module(db).into()),
             Definition::Local(it) => it.parent(db).try_into().ok(),
-            _ => None,
+            Definition::GenericParam(it) => Some(it.parent().into()),
+            Definition::Label(it) => it.parent(db).try_into().ok(),
+            Definition::ExternCrateDecl(it) => container_to_definition(it.container(db)),
+            Definition::DeriveHelper(it) => Some(it.derive().module(db).into()),
+            Definition::InlineAsmOperand(it) => it.parent(db).try_into().ok(),
+            Definition::BuiltinAttr(_)
+            | Definition::BuiltinType(_)
+            | Definition::BuiltinLifetime(_)
+            | Definition::TupleField(_)
+            | Definition::ToolModule(_)
+            | Definition::InlineAsmRegOrRegClass(_) => None,
         }
     }
 
@@ -304,7 +335,7 @@ fn find_std_module(
     let std_crate = famous_defs.std()?;
     let std_root_module = std_crate.root_module();
     std_root_module.children(db).find(|module| {
-        module.name(db).map_or(false, |module| module.display(db, edition).to_string() == name)
+        module.name(db).is_some_and(|module| module.display(db, edition).to_string() == name)
     })
 }
 
@@ -359,24 +390,32 @@ impl IdentClass {
             .or_else(|| NameClass::classify_lifetime(sema, lifetime).map(IdentClass::NameClass))
     }
 
-    pub fn definitions(self) -> ArrayVec<Definition, 2> {
+    pub fn definitions(self) -> ArrayVec<(Definition, Option<GenericSubstitution>), 2> {
         let mut res = ArrayVec::new();
         match self {
             IdentClass::NameClass(NameClass::Definition(it) | NameClass::ConstReference(it)) => {
-                res.push(it)
+                res.push((it, None))
             }
-            IdentClass::NameClass(NameClass::PatFieldShorthand { local_def, field_ref }) => {
-                res.push(Definition::Local(local_def));
-                res.push(Definition::Field(field_ref));
+            IdentClass::NameClass(NameClass::PatFieldShorthand {
+                local_def,
+                field_ref,
+                adt_subst,
+            }) => {
+                res.push((Definition::Local(local_def), None));
+                res.push((Definition::Field(field_ref), Some(adt_subst)));
             }
-            IdentClass::NameRefClass(NameRefClass::Definition(it)) => res.push(it),
-            IdentClass::NameRefClass(NameRefClass::FieldShorthand { local_ref, field_ref }) => {
-                res.push(Definition::Local(local_ref));
-                res.push(Definition::Field(field_ref));
+            IdentClass::NameRefClass(NameRefClass::Definition(it, subst)) => res.push((it, subst)),
+            IdentClass::NameRefClass(NameRefClass::FieldShorthand {
+                local_ref,
+                field_ref,
+                adt_subst,
+            }) => {
+                res.push((Definition::Local(local_ref), None));
+                res.push((Definition::Field(field_ref), Some(adt_subst)));
             }
             IdentClass::NameRefClass(NameRefClass::ExternCrateShorthand { decl, krate }) => {
-                res.push(Definition::ExternCrateDecl(decl));
-                res.push(Definition::Module(krate.root_module()));
+                res.push((Definition::ExternCrateDecl(decl), None));
+                res.push((Definition::Module(krate.root_module()), None));
             }
             IdentClass::Operator(
                 OperatorClass::Await(func)
@@ -384,9 +423,9 @@ impl IdentClass {
                 | OperatorClass::Bin(func)
                 | OperatorClass::Index(func)
                 | OperatorClass::Try(func),
-            ) => res.push(Definition::Function(func)),
+            ) => res.push((Definition::Function(func), None)),
             IdentClass::Operator(OperatorClass::Range(struct0)) => {
-                res.push(Definition::Adt(Adt::Struct(struct0)))
+                res.push((Definition::Adt(Adt::Struct(struct0)), None))
             }
         }
         res
@@ -398,12 +437,20 @@ impl IdentClass {
             IdentClass::NameClass(NameClass::Definition(it) | NameClass::ConstReference(it)) => {
                 res.push(it)
             }
-            IdentClass::NameClass(NameClass::PatFieldShorthand { local_def, field_ref }) => {
+            IdentClass::NameClass(NameClass::PatFieldShorthand {
+                local_def,
+                field_ref,
+                adt_subst: _,
+            }) => {
                 res.push(Definition::Local(local_def));
                 res.push(Definition::Field(field_ref));
             }
-            IdentClass::NameRefClass(NameRefClass::Definition(it)) => res.push(it),
-            IdentClass::NameRefClass(NameRefClass::FieldShorthand { local_ref, field_ref }) => {
+            IdentClass::NameRefClass(NameRefClass::Definition(it, _)) => res.push(it),
+            IdentClass::NameRefClass(NameRefClass::FieldShorthand {
+                local_ref,
+                field_ref,
+                adt_subst: _,
+            }) => {
                 res.push(Definition::Local(local_ref));
                 res.push(Definition::Field(field_ref));
             }
@@ -437,6 +484,7 @@ pub enum NameClass {
     PatFieldShorthand {
         local_def: Local,
         field_ref: Field,
+        adt_subst: GenericSubstitution,
     },
 }
 
@@ -446,7 +494,7 @@ impl NameClass {
         let res = match self {
             NameClass::Definition(it) => it,
             NameClass::ConstReference(_) => return None,
-            NameClass::PatFieldShorthand { local_def, field_ref: _ } => {
+            NameClass::PatFieldShorthand { local_def, field_ref: _, adt_subst: _ } => {
                 Definition::Local(local_def)
             }
         };
@@ -517,10 +565,13 @@ impl NameClass {
             let pat_parent = ident_pat.syntax().parent();
             if let Some(record_pat_field) = pat_parent.and_then(ast::RecordPatField::cast) {
                 if record_pat_field.name_ref().is_none() {
-                    if let Some((field, _)) = sema.resolve_record_pat_field(&record_pat_field) {
+                    if let Some((field, _, adt_subst)) =
+                        sema.resolve_record_pat_field_with_subst(&record_pat_field)
+                    {
                         return Some(NameClass::PatFieldShorthand {
                             local_def: local,
                             field_ref: field,
+                            adt_subst,
                         });
                     }
                 }
@@ -629,10 +680,11 @@ impl OperatorClass {
 /// reference to point to two different defs.
 #[derive(Debug)]
 pub enum NameRefClass {
-    Definition(Definition),
+    Definition(Definition, Option<GenericSubstitution>),
     FieldShorthand {
         local_ref: Local,
         field_ref: Field,
+        adt_subst: GenericSubstitution,
     },
     /// The specific situation where we have an extern crate decl without a rename
     /// Here we have both a declaration and a reference.
@@ -657,12 +709,16 @@ impl NameRefClass {
         let parent = name_ref.syntax().parent()?;
 
         if let Some(record_field) = ast::RecordExprField::for_field_name(name_ref) {
-            if let Some((field, local, _)) = sema.resolve_record_field(&record_field) {
+            if let Some((field, local, _, adt_subst)) =
+                sema.resolve_record_field_with_substitution(&record_field)
+            {
                 let res = match local {
-                    None => NameRefClass::Definition(Definition::Field(field)),
-                    Some(local) => {
-                        NameRefClass::FieldShorthand { field_ref: field, local_ref: local }
-                    }
+                    None => NameRefClass::Definition(Definition::Field(field), Some(adt_subst)),
+                    Some(local) => NameRefClass::FieldShorthand {
+                        field_ref: field,
+                        local_ref: local,
+                        adt_subst,
+                    },
                 };
                 return Some(res);
             }
@@ -674,44 +730,43 @@ impl NameRefClass {
                     // Only use this to resolve to macro calls for last segments as qualifiers resolve
                     // to modules below.
                     if let Some(macro_def) = sema.resolve_macro_call(&macro_call) {
-                        return Some(NameRefClass::Definition(Definition::Macro(macro_def)));
+                        return Some(NameRefClass::Definition(Definition::Macro(macro_def), None));
                     }
                 }
             }
-            return sema.resolve_path(&path).map(Into::into).map(NameRefClass::Definition);
+            return sema
+                .resolve_path_with_subst(&path)
+                .map(|(res, subst)| NameRefClass::Definition(res.into(), subst));
         }
 
         match_ast! {
             match parent {
                 ast::MethodCallExpr(method_call) => {
                     sema.resolve_method_call_fallback(&method_call)
-                        .map(|it| {
-                            it.map_left(Definition::Function)
-                                .map_right(Definition::Field)
-                                .either(NameRefClass::Definition, NameRefClass::Definition)
+                        .map(|(def, subst)| {
+                            match def {
+                                Either::Left(def) => NameRefClass::Definition(def.into(), subst),
+                                Either::Right(def) => NameRefClass::Definition(def.into(), subst),
+                            }
                         })
                 },
                 ast::FieldExpr(field_expr) => {
                     sema.resolve_field_fallback(&field_expr)
-                    .map(|it| {
-                        NameRefClass::Definition(match it {
-                            Either::Left(Either::Left(field)) => Definition::Field(field),
-                            Either::Left(Either::Right(field)) => Definition::TupleField(field),
-                            Either::Right(fun) => Definition::Function(fun),
+                        .map(|(def, subst)| {
+                            match def {
+                                Either::Left(Either::Left(def)) => NameRefClass::Definition(def.into(), subst),
+                                Either::Left(Either::Right(def)) => NameRefClass::Definition(Definition::TupleField(def), subst),
+                                Either::Right(def) => NameRefClass::Definition(def.into(), subst),
+                            }
                         })
-                    })
                 },
                 ast::RecordPatField(record_pat_field) => {
-                    sema.resolve_record_pat_field(&record_pat_field)
-                        .map(|(field, ..)|field)
-                        .map(Definition::Field)
-                        .map(NameRefClass::Definition)
+                    sema.resolve_record_pat_field_with_subst(&record_pat_field)
+                        .map(|(field, _, subst)| NameRefClass::Definition(Definition::Field(field), Some(subst)))
                 },
                 ast::RecordExprField(record_expr_field) => {
-                    sema.resolve_record_field(&record_expr_field)
-                        .map(|(field, ..)|field)
-                        .map(Definition::Field)
-                        .map(NameRefClass::Definition)
+                    sema.resolve_record_field_with_substitution(&record_expr_field)
+                        .map(|(field, _, _, subst)| NameRefClass::Definition(Definition::Field(field), Some(subst)))
                 },
                 ast::AssocTypeArg(_) => {
                     // `Trait<Assoc = Ty>`
@@ -728,28 +783,30 @@ impl NameRefClass {
                             })
                             .find(|alias| alias.name(sema.db).eq_ident(name_ref.text().as_str()))
                         {
-                            return Some(NameRefClass::Definition(Definition::TypeAlias(ty)));
+                            // No substitution, this can only occur in type position.
+                            return Some(NameRefClass::Definition(Definition::TypeAlias(ty), None));
                         }
                     }
                     None
                 },
                 ast::UseBoundGenericArgs(_) => {
+                    // No substitution, this can only occur in type position.
                     sema.resolve_use_type_arg(name_ref)
                         .map(GenericParam::TypeParam)
                         .map(Definition::GenericParam)
-                        .map(NameRefClass::Definition)
+                        .map(|it| NameRefClass::Definition(it, None))
                 },
                 ast::ExternCrate(extern_crate_ast) => {
                     let extern_crate = sema.to_def(&extern_crate_ast)?;
                     let krate = extern_crate.resolved_crate(sema.db)?;
                     Some(if extern_crate_ast.rename().is_some() {
-                        NameRefClass::Definition(Definition::Module(krate.root_module()))
+                        NameRefClass::Definition(Definition::Module(krate.root_module()), None)
                     } else {
                         NameRefClass::ExternCrateShorthand { krate, decl: extern_crate }
                     })
                 },
                 ast::AsmRegSpec(_) => {
-                    Some(NameRefClass::Definition(Definition::InlineAsmRegOrRegClass(())))
+                    Some(NameRefClass::Definition(Definition::InlineAsmRegOrRegClass(()), None))
                 },
                 _ => None
             }
@@ -762,13 +819,17 @@ impl NameRefClass {
     ) -> Option<NameRefClass> {
         let _p = tracing::info_span!("NameRefClass::classify_lifetime", ?lifetime).entered();
         if lifetime.text() == "'static" {
-            return Some(NameRefClass::Definition(Definition::BuiltinLifetime(StaticLifetime)));
+            return Some(NameRefClass::Definition(
+                Definition::BuiltinLifetime(StaticLifetime),
+                None,
+            ));
         }
         let parent = lifetime.syntax().parent()?;
         match parent.kind() {
-            SyntaxKind::BREAK_EXPR | SyntaxKind::CONTINUE_EXPR => {
-                sema.resolve_label(lifetime).map(Definition::Label).map(NameRefClass::Definition)
-            }
+            SyntaxKind::BREAK_EXPR | SyntaxKind::CONTINUE_EXPR => sema
+                .resolve_label(lifetime)
+                .map(Definition::Label)
+                .map(|it| NameRefClass::Definition(it, None)),
             SyntaxKind::LIFETIME_ARG
             | SyntaxKind::USE_BOUND_GENERIC_ARGS
             | SyntaxKind::SELF_PARAM
@@ -778,7 +839,7 @@ impl NameRefClass {
                 .resolve_lifetime_param(lifetime)
                 .map(GenericParam::LifetimeParam)
                 .map(Definition::GenericParam)
-                .map(NameRefClass::Definition),
+                .map(|it| NameRefClass::Definition(it, None)),
             _ => None,
         }
     }
@@ -901,3 +962,17 @@ impl TryFrom<DefWithBody> for Definition {
         }
     }
 }
+
+impl From<GenericDef> for Definition {
+    fn from(def: GenericDef) -> Self {
+        match def {
+            GenericDef::Function(it) => it.into(),
+            GenericDef::Adt(it) => it.into(),
+            GenericDef::Trait(it) => it.into(),
+            GenericDef::TraitAlias(it) => it.into(),
+            GenericDef::TypeAlias(it) => it.into(),
+            GenericDef::Impl(it) => it.into(),
+            GenericDef::Const(it) => it.into(),
+        }
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/documentation.rs b/src/tools/rust-analyzer/crates/ide-db/src/documentation.rs
index b52a325790b..a0ef0f90a65 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/documentation.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/documentation.rs
@@ -226,9 +226,8 @@ impl HasDocs for hir::AssocItem {
 
 impl HasDocs for hir::ExternCrateDecl {
     fn docs(self, db: &dyn HirDatabase) -> Option<Documentation> {
-        let crate_docs =
-            docs_from_attrs(&self.resolved_crate(db)?.root_module().attrs(db)).map(String::from);
-        let decl_docs = docs_from_attrs(&self.attrs(db)).map(String::from);
+        let crate_docs = docs_from_attrs(&self.resolved_crate(db)?.root_module().attrs(db));
+        let decl_docs = docs_from_attrs(&self.attrs(db));
         match (decl_docs, crate_docs) {
             (None, None) => None,
             (Some(decl_docs), None) => Some(decl_docs),
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs
index dab36bf20b9..8f0be1d9035 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs
@@ -706,7 +706,7 @@ fn path_import_candidate(
     Some(match qualifier {
         Some(qualifier) => match sema.resolve_path(&qualifier) {
             Some(PathResolution::Def(ModuleDef::BuiltinType(_))) | None => {
-                if qualifier.first_qualifier().map_or(true, |it| sema.resolve_path(&it).is_none()) {
+                if qualifier.first_qualifier().is_none_or(|it| sema.resolve_path(&it).is_none()) {
                     let qualifier = qualifier
                         .segments()
                         .map(|seg| seg.name_ref().map(|name| SmolStr::new(name.text())))
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs
index fc86d169a24..8e25ad3472d 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/insert_use.rs
@@ -72,9 +72,7 @@ impl ImportScope {
     fn from(syntax: SyntaxNode) -> Option<Self> {
         use syntax::match_ast;
         fn contains_cfg_attr(attrs: &dyn HasAttrs) -> bool {
-            attrs
-                .attrs()
-                .any(|attr| attr.as_simple_call().map_or(false, |(ident, _)| ident == "cfg"))
+            attrs.attrs().any(|attr| attr.as_simple_call().is_some_and(|(ident, _)| ident == "cfg"))
         }
         match_ast! {
             match syntax {
@@ -102,9 +100,7 @@ impl ImportScope {
         sema: &Semantics<'_, RootDatabase>,
     ) -> Option<Self> {
         fn contains_cfg_attr(attrs: &dyn HasAttrs) -> bool {
-            attrs
-                .attrs()
-                .any(|attr| attr.as_simple_call().map_or(false, |(ident, _)| ident == "cfg"))
+            attrs.attrs().any(|attr| attr.as_simple_call().is_some_and(|(ident, _)| ident == "cfg"))
         }
 
         // Walk up the ancestor tree searching for a suitable node to do insertions on
@@ -487,7 +483,7 @@ fn insert_use_(scope: &ImportScope, use_item: ast::Use, group_imports: bool) {
                     .contains(&token.kind())
             }
         })
-        .filter(|child| child.as_token().map_or(true, |t| t.kind() != SyntaxKind::WHITESPACE))
+        .filter(|child| child.as_token().is_none_or(|t| t.kind() != SyntaxKind::WHITESPACE))
         .last()
     {
         cov_mark::hit!(insert_empty_inner_attr);
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs
index 4c197b45338..9e89dfe87ab 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/merge_imports.rs
@@ -290,7 +290,7 @@ pub fn try_normalize_use_tree_mut(
 fn recursive_normalize(use_tree: &ast::UseTree, style: NormalizationStyle) -> Option<()> {
     let use_tree_list = use_tree.use_tree_list()?;
     let merge_subtree_into_parent_tree = |single_subtree: &ast::UseTree| {
-        let subtree_is_only_self = single_subtree.path().as_ref().map_or(false, path_is_self);
+        let subtree_is_only_self = single_subtree.path().as_ref().is_some_and(path_is_self);
 
         let merged_path = match (use_tree.path(), single_subtree.path()) {
             // If the subtree is `{self}` then we cannot merge: `use
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 1f77ea1ec66..b3105e6524d 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
@@ -320,7 +320,7 @@ impl<'a> Ranker<'a> {
         let same_text = tok.text() == self.text;
         // anything that mapped into a token tree has likely no semantic information
         let no_tt_parent =
-            tok.parent().map_or(false, |it| it.kind() != parser::SyntaxKind::TOKEN_TREE);
+            tok.parent().is_some_and(|it| it.kind() != parser::SyntaxKind::TOKEN_TREE);
         (both_idents as usize)
             | ((exact_same_kind as usize) << 1)
             | ((same_text as usize) << 2)
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
index 156f21b784e..a045c22c2df 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
@@ -285,7 +285,7 @@ impl Ctx<'_> {
         if path.qualifier().is_some() {
             return None;
         }
-        if path.segment().map_or(false, |s| {
+        if path.segment().is_some_and(|s| {
             s.parenthesized_arg_list().is_some()
                 || (s.self_token().is_some() && path.parent_path().is_none())
         }) {
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/search.rs b/src/tools/rust-analyzer/crates/ide-db/src/search.rs
index c5215eb3e63..68199dd8711 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/search.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/search.rs
@@ -1081,7 +1081,7 @@ impl<'a> FindUsages<'a> {
         };
 
         match NameRefClass::classify(self.sema, name_ref) {
-            Some(NameRefClass::Definition(Definition::SelfType(impl_)))
+            Some(NameRefClass::Definition(Definition::SelfType(impl_), _))
                 if ty_eq(impl_.self_ty(self.sema.db)) =>
             {
                 let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax());
@@ -1102,7 +1102,7 @@ impl<'a> FindUsages<'a> {
         sink: &mut dyn FnMut(EditionedFileId, FileReference) -> bool,
     ) -> bool {
         match NameRefClass::classify(self.sema, name_ref) {
-            Some(NameRefClass::Definition(def @ Definition::Module(_))) if def == self.def => {
+            Some(NameRefClass::Definition(def @ Definition::Module(_), _)) if def == self.def => {
                 let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax());
                 let category = if is_name_ref_in_import(name_ref) {
                     ReferenceCategory::IMPORT
@@ -1147,7 +1147,7 @@ impl<'a> FindUsages<'a> {
         sink: &mut dyn FnMut(EditionedFileId, FileReference) -> bool,
     ) -> bool {
         match NameRefClass::classify_lifetime(self.sema, lifetime) {
-            Some(NameRefClass::Definition(def)) if def == self.def => {
+            Some(NameRefClass::Definition(def, _)) if def == self.def => {
                 let FileRange { file_id, range } = self.sema.original_range(lifetime.syntax());
                 let reference = FileReference {
                     range,
@@ -1166,7 +1166,7 @@ impl<'a> FindUsages<'a> {
         sink: &mut dyn FnMut(EditionedFileId, FileReference) -> bool,
     ) -> bool {
         match NameRefClass::classify(self.sema, name_ref) {
-            Some(NameRefClass::Definition(def))
+            Some(NameRefClass::Definition(def, _))
                 if self.def == def
                     // is our def a trait assoc item? then we want to find all assoc items from trait impls of our trait
                     || matches!(self.assoc_item_container, Some(hir::AssocItemContainer::Trait(_)))
@@ -1182,7 +1182,7 @@ impl<'a> FindUsages<'a> {
             }
             // FIXME: special case type aliases, we can't filter between impl and trait defs here as we lack the substitutions
             // so we always resolve all assoc type aliases to both their trait def and impl defs
-            Some(NameRefClass::Definition(def))
+            Some(NameRefClass::Definition(def, _))
                 if self.assoc_item_container.is_some()
                     && matches!(self.def, Definition::TypeAlias(_))
                     && convert_to_def_in_trait(self.sema.db, def)
@@ -1196,7 +1196,7 @@ impl<'a> FindUsages<'a> {
                 };
                 sink(file_id, reference)
             }
-            Some(NameRefClass::Definition(def)) if self.include_self_kw_refs.is_some() => {
+            Some(NameRefClass::Definition(def, _)) if self.include_self_kw_refs.is_some() => {
                 if self.include_self_kw_refs == def_to_ty(self.sema, &def) {
                     let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax());
                     let reference = FileReference {
@@ -1209,7 +1209,11 @@ impl<'a> FindUsages<'a> {
                     false
                 }
             }
-            Some(NameRefClass::FieldShorthand { local_ref: local, field_ref: field }) => {
+            Some(NameRefClass::FieldShorthand {
+                local_ref: local,
+                field_ref: field,
+                adt_subst: _,
+            }) => {
                 let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax());
 
                 let field = Definition::Field(field);
@@ -1240,7 +1244,7 @@ impl<'a> FindUsages<'a> {
         sink: &mut dyn FnMut(EditionedFileId, FileReference) -> bool,
     ) -> bool {
         match NameClass::classify(self.sema, name) {
-            Some(NameClass::PatFieldShorthand { local_def: _, field_ref })
+            Some(NameClass::PatFieldShorthand { local_def: _, field_ref, adt_subst: _ })
                 if matches!(
                     self.def, Definition::Field(_) if Definition::Field(field_ref) == self.def
                 ) =>
@@ -1352,12 +1356,12 @@ fn is_name_ref_in_import(name_ref: &ast::NameRef) -> bool {
         .parent()
         .and_then(ast::PathSegment::cast)
         .and_then(|it| it.parent_path().top_path().syntax().parent())
-        .map_or(false, |it| it.kind() == SyntaxKind::USE_TREE)
+        .is_some_and(|it| it.kind() == SyntaxKind::USE_TREE)
 }
 
 fn is_name_ref_in_test(sema: &Semantics<'_, RootDatabase>, name_ref: &ast::NameRef) -> bool {
     name_ref.syntax().ancestors().any(|node| match ast::Fn::cast(node) {
-        Some(it) => sema.to_def(&it).map_or(false, |func| func.is_test(sema.db)),
+        Some(it) => sema.to_def(&it).is_some_and(|func| func.is_test(sema.db)),
         None => false,
     })
 }
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs
index 91e0b4495f5..74c0b8e2baa 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/node_ext.rs
@@ -220,7 +220,7 @@ pub fn vis_eq(this: &ast::Visibility, other: &ast::Visibility) -> bool {
     match (this.kind(), other.kind()) {
         (VisibilityKind::In(this), VisibilityKind::In(other)) => {
             stdx::iter_eq_by(this.segments(), other.segments(), |lhs, rhs| {
-                lhs.kind().zip(rhs.kind()).map_or(false, |it| match it {
+                lhs.kind().zip(rhs.kind()).is_some_and(|it| match it {
                     (PathSegmentKind::CrateKw, PathSegmentKind::CrateKw)
                     | (PathSegmentKind::SelfKw, PathSegmentKind::SelfKw)
                     | (PathSegmentKind::SuperKw, PathSegmentKind::SuperKw) => true,
@@ -259,7 +259,7 @@ pub fn is_pattern_cond(expr: ast::Expr) -> bool {
                 .or_else(|| expr.rhs().map(is_pattern_cond))
                 .unwrap_or(false)
         }
-        ast::Expr::ParenExpr(expr) => expr.expr().map_or(false, is_pattern_cond),
+        ast::Expr::ParenExpr(expr) => expr.expr().is_some_and(is_pattern_cond),
         ast::Expr::LetExpr(_) => true,
         _ => false,
     }
@@ -408,7 +408,7 @@ fn for_each_break_expr(
 }
 
 pub fn eq_label_lt(lt1: &Option<ast::Lifetime>, lt2: &Option<ast::Lifetime>) -> bool {
-    lt1.as_ref().zip(lt2.as_ref()).map_or(false, |(lt, lbl)| lt.text() == lbl.text())
+    lt1.as_ref().zip(lt2.as_ref()).is_some_and(|(lt, lbl)| lt.text() == lbl.text())
 }
 
 struct TreeWithDepthIterator {
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs
index 1e08e8e3098..365d726d2a9 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs
@@ -2,13 +2,13 @@
 
 use std::{collections::hash_map::Entry, str::FromStr};
 
-use hir::Semantics;
+use hir::{Semantics, SemanticsScope};
 use itertools::Itertools;
 use rustc_hash::FxHashMap;
 use stdx::to_lower_snake_case;
 use syntax::{
     ast::{self, HasName},
-    match_ast, AstNode, Edition, SmolStr, SmolStrBuilder,
+    match_ast, AstNode, Edition, SmolStr, SmolStrBuilder, ToSmolStr,
 };
 
 use crate::RootDatabase;
@@ -100,6 +100,19 @@ impl NameGenerator {
         generator
     }
 
+    pub fn new_from_scope_locals(scope: Option<SemanticsScope<'_>>) -> Self {
+        let mut generator = Self::new();
+        if let Some(scope) = scope {
+            scope.process_all_names(&mut |name, scope| {
+                if let hir::ScopeDef::Local(_) = scope {
+                    generator.insert(name.as_str());
+                }
+            });
+        }
+
+        generator
+    }
+
     /// Suggest a name without conflicts. If the name conflicts with existing names,
     /// it will try to resolve the conflict by adding a numeric suffix.
     pub fn suggest_name(&mut self, name: &str) -> SmolStr {
@@ -162,6 +175,59 @@ impl NameGenerator {
         self.suggest_name(&c.to_string())
     }
 
+    /// Suggest name of variable for given expression
+    ///
+    /// In current implementation, the function tries to get the name from
+    /// the following sources:
+    ///
+    /// * if expr is an argument to function/method, use parameter name
+    /// * if expr is a function/method call, use function name
+    /// * expression type name if it exists (E.g. `()`, `fn() -> ()` or `!` do not have names)
+    /// * fallback: `var_name`
+    ///
+    /// It also applies heuristics to filter out less informative names
+    ///
+    /// Currently it sticks to the first name found.
+    pub fn for_variable(
+        &mut self,
+        expr: &ast::Expr,
+        sema: &Semantics<'_, RootDatabase>,
+    ) -> SmolStr {
+        // `from_param` does not benefit from stripping it need the largest
+        // context possible so we check firstmost
+        if let Some(name) = from_param(expr, sema) {
+            return self.suggest_name(&name);
+        }
+
+        let mut next_expr = Some(expr.clone());
+        while let Some(expr) = next_expr {
+            let name = from_call(&expr)
+                .or_else(|| from_type(&expr, sema))
+                .or_else(|| from_field_name(&expr));
+            if let Some(name) = name {
+                return self.suggest_name(&name);
+            }
+
+            match expr {
+                ast::Expr::RefExpr(inner) => next_expr = inner.expr(),
+                ast::Expr::AwaitExpr(inner) => next_expr = inner.expr(),
+                // ast::Expr::BlockExpr(block) => expr = block.tail_expr(),
+                ast::Expr::CastExpr(inner) => next_expr = inner.expr(),
+                ast::Expr::MethodCallExpr(method) if is_useless_method(&method) => {
+                    next_expr = method.receiver();
+                }
+                ast::Expr::ParenExpr(inner) => next_expr = inner.expr(),
+                ast::Expr::TryExpr(inner) => next_expr = inner.expr(),
+                ast::Expr::PrefixExpr(prefix) if prefix.op_kind() == Some(ast::UnaryOp::Deref) => {
+                    next_expr = prefix.expr()
+                }
+                _ => break,
+            }
+        }
+
+        self.suggest_name("var_name")
+    }
+
     /// Insert a name into the pool
     fn insert(&mut self, name: &str) {
         let (prefix, suffix) = Self::split_numeric_suffix(name);
@@ -191,63 +257,8 @@ impl NameGenerator {
     }
 }
 
-/// Suggest name of variable for given expression
-///
-/// **NOTE**: it is caller's responsibility to guarantee uniqueness of the name.
-/// I.e. it doesn't look for names in scope.
-///
-/// # Current implementation
-///
-/// In current implementation, the function tries to get the name from
-/// the following sources:
-///
-/// * if expr is an argument to function/method, use parameter name
-/// * if expr is a function/method call, use function name
-/// * expression type name if it exists (E.g. `()`, `fn() -> ()` or `!` do not have names)
-/// * fallback: `var_name`
-///
-/// It also applies heuristics to filter out less informative names
-///
-/// Currently it sticks to the first name found.
-// FIXME: Microoptimize and return a `SmolStr` here.
-pub fn for_variable(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> String {
-    // `from_param` does not benefit from stripping
-    // it need the largest context possible
-    // so we check firstmost
-    if let Some(name) = from_param(expr, sema) {
-        return name;
-    }
-
-    let mut next_expr = Some(expr.clone());
-    while let Some(expr) = next_expr {
-        let name =
-            from_call(&expr).or_else(|| from_type(&expr, sema)).or_else(|| from_field_name(&expr));
-        if let Some(name) = name {
-            return name;
-        }
-
-        match expr {
-            ast::Expr::RefExpr(inner) => next_expr = inner.expr(),
-            ast::Expr::AwaitExpr(inner) => next_expr = inner.expr(),
-            // ast::Expr::BlockExpr(block) => expr = block.tail_expr(),
-            ast::Expr::CastExpr(inner) => next_expr = inner.expr(),
-            ast::Expr::MethodCallExpr(method) if is_useless_method(&method) => {
-                next_expr = method.receiver();
-            }
-            ast::Expr::ParenExpr(inner) => next_expr = inner.expr(),
-            ast::Expr::TryExpr(inner) => next_expr = inner.expr(),
-            ast::Expr::PrefixExpr(prefix) if prefix.op_kind() == Some(ast::UnaryOp::Deref) => {
-                next_expr = prefix.expr()
-            }
-            _ => break,
-        }
-    }
-
-    "var_name".to_owned()
-}
-
-fn normalize(name: &str) -> Option<String> {
-    let name = to_lower_snake_case(name);
+fn normalize(name: &str) -> Option<SmolStr> {
+    let name = to_lower_snake_case(name).to_smolstr();
 
     if USELESS_NAMES.contains(&name.as_str()) {
         return None;
@@ -280,11 +291,11 @@ fn is_useless_method(method: &ast::MethodCallExpr) -> bool {
     }
 }
 
-fn from_call(expr: &ast::Expr) -> Option<String> {
+fn from_call(expr: &ast::Expr) -> Option<SmolStr> {
     from_func_call(expr).or_else(|| from_method_call(expr))
 }
 
-fn from_func_call(expr: &ast::Expr) -> Option<String> {
+fn from_func_call(expr: &ast::Expr) -> Option<SmolStr> {
     let call = match expr {
         ast::Expr::CallExpr(call) => call,
         _ => return None,
@@ -297,7 +308,7 @@ fn from_func_call(expr: &ast::Expr) -> Option<String> {
     normalize(ident.text())
 }
 
-fn from_method_call(expr: &ast::Expr) -> Option<String> {
+fn from_method_call(expr: &ast::Expr) -> Option<SmolStr> {
     let method = match expr {
         ast::Expr::MethodCallExpr(call) => call,
         _ => return None,
@@ -319,7 +330,7 @@ fn from_method_call(expr: &ast::Expr) -> Option<String> {
     normalize(name)
 }
 
-fn from_param(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option<String> {
+fn from_param(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option<SmolStr> {
     let arg_list = expr.syntax().parent().and_then(ast::ArgList::cast)?;
     let args_parent = arg_list.syntax().parent()?;
     let func = match_ast! {
@@ -338,7 +349,7 @@ fn from_param(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option<St
     let param = func.params().into_iter().nth(idx)?;
     let pat = sema.source(param)?.value.right()?.pat()?;
     let name = var_name_from_pat(&pat)?;
-    normalize(&name.to_string())
+    normalize(&name.to_smolstr())
 }
 
 fn var_name_from_pat(pat: &ast::Pat) -> Option<ast::Name> {
@@ -350,7 +361,7 @@ fn var_name_from_pat(pat: &ast::Pat) -> Option<ast::Name> {
     }
 }
 
-fn from_type(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option<String> {
+fn from_type(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option<SmolStr> {
     let ty = sema.type_of_expr(expr)?.adjusted();
     let ty = ty.remove_ref().unwrap_or(ty);
     let edition = sema.scope(expr.syntax())?.krate().edition(sema.db);
@@ -358,7 +369,7 @@ fn from_type(expr: &ast::Expr, sema: &Semantics<'_, RootDatabase>) -> Option<Str
     name_of_type(&ty, sema.db, edition)
 }
 
-fn name_of_type(ty: &hir::Type, db: &RootDatabase, edition: Edition) -> Option<String> {
+fn name_of_type(ty: &hir::Type, db: &RootDatabase, edition: Edition) -> Option<SmolStr> {
     let name = if let Some(adt) = ty.as_adt() {
         let name = adt.name(db).display(db, edition).to_string();
 
@@ -393,7 +404,7 @@ fn trait_name(trait_: &hir::Trait, db: &RootDatabase, edition: Edition) -> Optio
     Some(name)
 }
 
-fn from_field_name(expr: &ast::Expr) -> Option<String> {
+fn from_field_name(expr: &ast::Expr) -> Option<SmolStr> {
     let field = match expr {
         ast::Expr::FieldExpr(field) => field,
         _ => return None,
@@ -424,7 +435,7 @@ mod tests {
             frange.range,
             "selection is not an expression(yet contained in one)"
         );
-        let name = for_variable(&expr, &sema);
+        let name = NameGenerator::new().for_variable(&expr, &sema);
         assert_eq!(&name, expected);
     }
 
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs
index a319a0bcf6d..2b59c1a22f6 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/generic_args_prohibited.rs
@@ -34,6 +34,8 @@ fn describe_reason(reason: GenericArgsProhibitedReason) -> String {
             return "you can specify generic arguments on either the enum or the variant, but not both"
                 .to_owned();
         }
+        GenericArgsProhibitedReason::Const => "constants",
+        GenericArgsProhibitedReason::Static => "statics",
     };
     format!("generic arguments are not allowed on {kind}")
 }
@@ -439,4 +441,167 @@ impl Trait for () {
         "#,
         );
     }
+
+    #[test]
+    fn in_record_expr() {
+        check_diagnostics(
+            r#"
+mod foo {
+    pub struct Bar { pub field: i32 }
+}
+fn baz() {
+    let _ = foo::<()>::Bar { field: 0 };
+            // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+}
+        "#,
+        );
+    }
+
+    #[test]
+    fn in_record_pat() {
+        check_diagnostics(
+            r#"
+mod foo {
+    pub struct Bar { field: i32 }
+}
+fn baz(v: foo::Bar) {
+    let foo::<()>::Bar { .. } = v;
+        // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+}
+        "#,
+        );
+    }
+
+    #[test]
+    fn in_tuple_struct_pat() {
+        check_diagnostics(
+            r#"
+mod foo {
+    pub struct Bar(i32);
+}
+fn baz(v: foo::Bar) {
+    let foo::<()>::Bar(..) = v;
+        // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+}
+        "#,
+        );
+    }
+
+    #[test]
+    fn in_path_pat() {
+        check_diagnostics(
+            r#"
+mod foo {
+    pub struct Bar;
+}
+fn baz(v: foo::Bar) {
+    let foo::<()>::Bar = v;
+        // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+}
+        "#,
+        );
+    }
+
+    #[test]
+    fn in_path_expr() {
+        check_diagnostics(
+            r#"
+mod foo {
+    pub struct Bar;
+}
+fn baz() {
+    let _ = foo::<()>::Bar;
+            // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+}
+        "#,
+        );
+    }
+
+    #[test]
+    fn const_and_static() {
+        check_diagnostics(
+            r#"
+const CONST: i32 = 0;
+static STATIC: i32 = 0;
+fn baz() {
+    let _ = CONST::<()>;
+              // ^^^^^^ 💡 error: generic arguments are not allowed on constants
+    let _ = STATIC::<()>;
+               // ^^^^^^ 💡 error: generic arguments are not allowed on statics
+}
+        "#,
+        );
+    }
+
+    #[test]
+    fn enum_variant() {
+        check_diagnostics(
+            r#"
+enum Enum<A> {
+    Variant(A),
+}
+mod enum_ {
+    pub(super) use super::Enum::Variant as V;
+}
+fn baz() {
+    let v = Enum::<()>::Variant::<()>(());
+                            // ^^^^^^ 💡 error: you can specify generic arguments on either the enum or the variant, but not both
+    let Enum::<()>::Variant::<()>(..) = v;
+                        // ^^^^^^ 💡 error: you can specify generic arguments on either the enum or the variant, but not both
+    let _ = Enum::<()>::Variant(());
+    let _ = Enum::Variant::<()>(());
+}
+fn foo() {
+    use Enum::Variant;
+    let _ = Variant::<()>(());
+    let _ = enum_::V::<()>(());
+    let _ = enum_::<()>::V::<()>(());
+              // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+}
+        "#,
+        );
+    }
+
+    #[test]
+    fn dyn_trait() {
+        check_diagnostics(
+            r#"
+mod foo {
+    pub trait Trait {}
+}
+
+fn bar() {
+    let _: &dyn foo::<()>::Trait;
+                // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+    let _: &foo::<()>::Trait;
+            // ^^^^^^ 💡 error: generic arguments are not allowed on modules
+}
+        "#,
+        );
+    }
+
+    #[test]
+    fn regression_18768() {
+        check_diagnostics(
+            r#"
+//- minicore: result
+//- /foo.rs crate:foo edition:2018
+pub mod lib {
+    mod core {
+        pub use core::*;
+    }
+    pub use self::core::result;
+}
+
+pub mod __private {
+    pub use crate::lib::result::Result::{self, Err, Ok};
+}
+
+//- /bar.rs crate:bar deps:foo edition:2018
+fn bar() {
+    _ = foo::__private::Result::<(), ()>::Ok;
+}
+        "#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
index 5f38d13570a..8117401a534 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs
@@ -237,6 +237,24 @@ fn main() {
     fn no_missing_unsafe_diagnostic_with_safe_intrinsic() {
         check_diagnostics(
             r#"
+#[rustc_intrinsic]
+pub fn bitreverse(x: u32) -> u32; // Safe intrinsic
+#[rustc_intrinsic]
+pub unsafe fn floorf32(x: f32) -> f32; // Unsafe intrinsic
+
+fn main() {
+    let _ = bitreverse(12);
+    let _ = floorf32(12.0);
+          //^^^^^^^^^^^^^^💡 error: call to unsafe function is unsafe and requires an unsafe function or block
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn no_missing_unsafe_diagnostic_with_legacy_safe_intrinsic() {
+        check_diagnostics(
+            r#"
 extern "rust-intrinsic" {
     #[rustc_safe_intrinsic]
     pub fn bitreverse(x: u32) -> u32; // Safe intrinsic
diff --git a/src/tools/rust-analyzer/crates/ide/src/annotations.rs b/src/tools/rust-analyzer/crates/ide/src/annotations.rs
index 121a463c9f1..6a4e5ba290e 100644
--- a/src/tools/rust-analyzer/crates/ide/src/annotations.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/annotations.rs
@@ -316,6 +316,11 @@ fn main() {
                                 },
                                 kind: Bin,
                                 cfg: None,
+                                update_test: UpdateTest {
+                                    expect_test: false,
+                                    insta: false,
+                                    snapbox: false,
+                                },
                             },
                         ),
                     },
@@ -401,6 +406,11 @@ fn main() {
                                 },
                                 kind: Bin,
                                 cfg: None,
+                                update_test: UpdateTest {
+                                    expect_test: false,
+                                    insta: false,
+                                    snapbox: false,
+                                },
                             },
                         ),
                     },
@@ -537,6 +547,11 @@ fn main() {
                                 },
                                 kind: Bin,
                                 cfg: None,
+                                update_test: UpdateTest {
+                                    expect_test: false,
+                                    insta: false,
+                                    snapbox: false,
+                                },
                             },
                         ),
                     },
@@ -597,6 +612,11 @@ fn main() {}
                                 },
                                 kind: Bin,
                                 cfg: None,
+                                update_test: UpdateTest {
+                                    expect_test: false,
+                                    insta: false,
+                                    snapbox: false,
+                                },
                             },
                         ),
                     },
@@ -709,6 +729,11 @@ fn main() {
                                 },
                                 kind: Bin,
                                 cfg: None,
+                                update_test: UpdateTest {
+                                    expect_test: false,
+                                    insta: false,
+                                    snapbox: false,
+                                },
                             },
                         ),
                     },
@@ -746,6 +771,20 @@ mod tests {
                 [
                     Annotation {
                         range: 3..7,
+                        kind: HasReferences {
+                            pos: FilePositionWrapper {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                offset: 3,
+                            },
+                            data: Some(
+                                [],
+                            ),
+                        },
+                    },
+                    Annotation {
+                        range: 3..7,
                         kind: Runnable(
                             Runnable {
                                 use_name_in_title: false,
@@ -760,24 +799,15 @@ mod tests {
                                 },
                                 kind: Bin,
                                 cfg: None,
+                                update_test: UpdateTest {
+                                    expect_test: false,
+                                    insta: false,
+                                    snapbox: false,
+                                },
                             },
                         ),
                     },
                     Annotation {
-                        range: 3..7,
-                        kind: HasReferences {
-                            pos: FilePositionWrapper {
-                                file_id: FileId(
-                                    0,
-                                ),
-                                offset: 3,
-                            },
-                            data: Some(
-                                [],
-                            ),
-                        },
-                    },
-                    Annotation {
                         range: 18..23,
                         kind: Runnable(
                             Runnable {
@@ -796,6 +826,11 @@ mod tests {
                                     path: "tests",
                                 },
                                 cfg: None,
+                                update_test: UpdateTest {
+                                    expect_test: false,
+                                    insta: false,
+                                    snapbox: false,
+                                },
                             },
                         ),
                     },
@@ -822,6 +857,11 @@ mod tests {
                                     },
                                 },
                                 cfg: None,
+                                update_test: UpdateTest {
+                                    expect_test: false,
+                                    insta: false,
+                                    snapbox: false,
+                                },
                             },
                         ),
                     },
diff --git a/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs b/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs
index e5b4ed17b2a..8066894cd83 100644
--- a/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs
@@ -47,7 +47,7 @@ pub(crate) fn incoming_calls(
         .find_nodes_at_offset_with_descend(file, offset)
         .filter_map(move |node| match node {
             ast::NameLike::NameRef(name_ref) => match NameRefClass::classify(sema, &name_ref)? {
-                NameRefClass::Definition(def @ Definition::Function(_)) => Some(def),
+                NameRefClass::Definition(def @ Definition::Function(_), _) => Some(def),
                 _ => None,
             },
             ast::NameLike::Name(name) => match NameClass::classify(sema, &name)? {
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 ea16a11d56d..72fcac54177 100644
--- a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
@@ -147,8 +147,8 @@ pub(crate) fn external_docs(
     let definition = match_ast! {
         match node {
             ast::NameRef(name_ref) => match NameRefClass::classify(sema, &name_ref)? {
-                NameRefClass::Definition(def) => def,
-                NameRefClass::FieldShorthand { local_ref: _, field_ref } => {
+                NameRefClass::Definition(def, _) => def,
+                NameRefClass::FieldShorthand { local_ref: _, field_ref, adt_subst: _ } => {
                     Definition::Field(field_ref)
                 }
                 NameRefClass::ExternCrateShorthand { decl, .. } => {
@@ -157,7 +157,7 @@ pub(crate) fn external_docs(
             },
             ast::Name(name) => match NameClass::classify(sema, &name)? {
                 NameClass::Definition(it) | NameClass::ConstReference(it) => it,
-                NameClass::PatFieldShorthand { local_def: _, field_ref } => Definition::Field(field_ref),
+                NameClass::PatFieldShorthand { local_def: _, field_ref, adt_subst: _ } => Definition::Field(field_ref),
             },
             _ => return None
         }
diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links/intra_doc_links.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links/intra_doc_links.rs
index ebdd4add177..6cc240d6524 100644
--- a/src/tools/rust-analyzer/crates/ide/src/doc_links/intra_doc_links.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/doc_links/intra_doc_links.rs
@@ -25,7 +25,7 @@ pub(super) fn parse_intra_doc_link(s: &str) -> (&str, Option<hir::Namespace>) {
     .find_map(|(ns, (prefixes, suffixes))| {
         if let Some(prefix) = prefixes.iter().find(|&&prefix| {
             s.starts_with(prefix)
-                && s.chars().nth(prefix.len()).map_or(false, |c| c == '@' || c == ' ')
+                && s.chars().nth(prefix.len()).is_some_and(|c| c == '@' || c == ' ')
         }) {
             Some((&s[prefix.len() + 1..], ns))
         } else {
@@ -41,7 +41,7 @@ pub(super) fn strip_prefixes_suffixes(s: &str) -> &str {
         .find_map(|(prefixes, suffixes)| {
             if let Some(prefix) = prefixes.iter().find(|&&prefix| {
                 s.starts_with(prefix)
-                    && s.chars().nth(prefix.len()).map_or(false, |c| c == '@' || c == ' ')
+                    && s.chars().nth(prefix.len()).is_some_and(|c| c == '@' || c == ' ')
             }) {
                 Some(&s[prefix.len() + 1..])
             } else {
diff --git a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs
index 10a73edd51c..e028c5ff0cb 100644
--- a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs
@@ -253,6 +253,7 @@ fn _format(
     let &crate_id = db.relevant_crates(file_id).iter().next()?;
     let edition = db.crate_graph()[crate_id].edition;
 
+    #[allow(clippy::disallowed_methods)]
     let mut cmd = std::process::Command::new(toolchain::Tool::Rustfmt.path());
     cmd.arg("--edition");
     cmd.arg(edition.to_string());
@@ -573,7 +574,7 @@ struct Foo {}
 "#,
             expect![[r#"
                 Clone
-                impl < >core::clone::Clone for Foo< >where {
+                impl <>core::clone::Clone for Foo< >where {
                     fn clone(&self) -> Self {
                         match self {
                             Foo{}
@@ -599,7 +600,7 @@ struct Foo {}
 "#,
             expect![[r#"
                 Copy
-                impl < >core::marker::Copy for Foo< >where{}"#]],
+                impl <>core::marker::Copy for Foo< >where{}"#]],
         );
     }
 
@@ -614,7 +615,7 @@ struct Foo {}
 "#,
             expect![[r#"
                 Copy
-                impl < >core::marker::Copy for Foo< >where{}"#]],
+                impl <>core::marker::Copy for Foo< >where{}"#]],
         );
         check(
             r#"
@@ -625,7 +626,7 @@ struct Foo {}
 "#,
             expect![[r#"
                 Clone
-                impl < >core::clone::Clone for Foo< >where {
+                impl <>core::clone::Clone for Foo< >where {
                     fn clone(&self) -> Self {
                         match self {
                             Foo{}
diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs b/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs
index 9dacbd8badf..7b6a5ef13e5 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs
@@ -36,7 +36,7 @@ pub(crate) fn goto_declaration(
             let def = match_ast! {
                 match parent {
                     ast::NameRef(name_ref) => match NameRefClass::classify(&sema, &name_ref)? {
-                        NameRefClass::Definition(it) => Some(it),
+                        NameRefClass::Definition(it, _) => Some(it),
                         NameRefClass::FieldShorthand { field_ref, .. } =>
                             return field_ref.try_to_nav(db),
                         NameRefClass::ExternCrateShorthand { decl, .. } =>
diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
index 363f852e0e4..6c66907ec3e 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
@@ -103,7 +103,7 @@ pub(crate) fn goto_definition(
                 IdentClass::classify_node(sema, &parent)?
                     .definitions()
                     .into_iter()
-                    .flat_map(|def| {
+                    .flat_map(|(def, _)| {
                         if let Definition::ExternCrateDecl(crate_def) = def {
                             return crate_def
                                 .resolved_crate(db)
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 e36c8ee2f3f..04da1f67e95 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs
@@ -48,7 +48,7 @@ pub(crate) fn goto_implementation(
                     }
                     ast::NameLike::NameRef(name_ref) => NameRefClass::classify(&sema, name_ref)
                         .and_then(|class| match class {
-                            NameRefClass::Definition(def) => Some(def),
+                            NameRefClass::Definition(def, _) => Some(def),
                             NameRefClass::FieldShorthand { .. }
                             | NameRefClass::ExternCrateShorthand { .. } => None,
                         }),
diff --git a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
index 4690416e059..4002cbebad6 100644
--- a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
@@ -307,7 +307,7 @@ fn hl_exit_points(
         let range = match &expr {
             ast::Expr::TryExpr(try_) => try_.question_mark_token().map(|token| token.text_range()),
             ast::Expr::MethodCallExpr(_) | ast::Expr::CallExpr(_) | ast::Expr::MacroExpr(_)
-                if sema.type_of_expr(&expr).map_or(false, |ty| ty.original.is_never()) =>
+                if sema.type_of_expr(&expr).is_some_and(|ty| ty.original.is_never()) =>
             {
                 Some(expr.syntax().text_range())
             }
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs
index 332dfacbb43..1431bd8ca29 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs
@@ -6,7 +6,7 @@ mod tests;
 use std::{iter, ops::Not};
 
 use either::Either;
-use hir::{db::DefDatabase, HasCrate, HasSource, LangItem, Semantics};
+use hir::{db::DefDatabase, GenericSubstitution, HasCrate, HasSource, LangItem, Semantics};
 use ide_db::{
     defs::{Definition, IdentClass, NameRefClass, OperatorClass},
     famous_defs::FamousDefs,
@@ -35,6 +35,14 @@ pub struct HoverConfig {
     pub max_trait_assoc_items_count: Option<usize>,
     pub max_fields_count: Option<usize>,
     pub max_enum_variants_count: Option<usize>,
+    pub max_subst_ty_len: SubstTyLen,
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum SubstTyLen {
+    Unlimited,
+    LimitTo(usize),
+    Hide,
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -158,7 +166,8 @@ fn hover_offset(
     if let Some(doc_comment) = token_as_doc_comment(&original_token) {
         cov_mark::hit!(no_highlight_on_comment_hover);
         return doc_comment.get_definition_with_descend_at(sema, offset, |def, node, range| {
-            let res = hover_for_definition(sema, file_id, def, &node, None, false, config, edition);
+            let res =
+                hover_for_definition(sema, file_id, def, None, &node, None, false, config, edition);
             Some(RangeInfo::new(range, res))
         });
     }
@@ -170,6 +179,7 @@ fn hover_offset(
             sema,
             file_id,
             Definition::from(resolution?),
+            None,
             &original_token.parent()?,
             None,
             false,
@@ -217,7 +227,7 @@ fn hover_offset(
                             {
                                 if let Some(macro_) = sema.resolve_macro_call(&macro_call) {
                                     break 'a vec![(
-                                        Definition::Macro(macro_),
+                                        (Definition::Macro(macro_), None),
                                         sema.resolve_macro_call_arm(&macro_call),
                                         false,
                                         node,
@@ -236,7 +246,7 @@ fn hover_offset(
                             decl,
                             ..
                         }) => {
-                            vec![(Definition::ExternCrateDecl(decl), None, false, node)]
+                            vec![((Definition::ExternCrateDecl(decl), None), None, false, node)]
                         }
 
                         class => {
@@ -252,12 +262,13 @@ fn hover_offset(
                     }
                 }
                 .into_iter()
-                .unique_by(|&(def, _, _, _)| def)
-                .map(|(def, macro_arm, hovered_definition, node)| {
+                .unique_by(|&((def, _), _, _, _)| def)
+                .map(|((def, subst), macro_arm, hovered_definition, node)| {
                     hover_for_definition(
                         sema,
                         file_id,
                         def,
+                        subst,
                         &node,
                         macro_arm,
                         hovered_definition,
@@ -381,6 +392,7 @@ pub(crate) fn hover_for_definition(
     sema: &Semantics<'_, RootDatabase>,
     file_id: FileId,
     def: Definition,
+    subst: Option<GenericSubstitution>,
     scope_node: &SyntaxNode,
     macro_arm: Option<u32>,
     hovered_definition: bool,
@@ -408,6 +420,7 @@ pub(crate) fn hover_for_definition(
         _ => None,
     };
     let notable_traits = def_ty.map(|ty| notable_traits(db, &ty)).unwrap_or_default();
+    let subst_types = subst.map(|subst| subst.types(db));
 
     let markup = render::definition(
         sema.db,
@@ -416,6 +429,7 @@ pub(crate) fn hover_for_definition(
         &notable_traits,
         macro_arm,
         hovered_definition,
+        subst_types.as_ref(),
         config,
         edition,
     );
@@ -425,7 +439,7 @@ pub(crate) fn hover_for_definition(
             show_fn_references_action(sema.db, def),
             show_implementations_action(sema.db, def),
             runnable_action(sema, def, file_id),
-            goto_type_action_for_def(sema.db, def, &notable_traits, edition),
+            goto_type_action_for_def(sema.db, def, &notable_traits, subst_types, edition),
         ]
         .into_iter()
         .flatten()
@@ -517,6 +531,7 @@ fn goto_type_action_for_def(
     db: &RootDatabase,
     def: Definition,
     notable_traits: &[(hir::Trait, Vec<(Option<hir::Type>, hir::Name)>)],
+    subst_types: Option<Vec<(hir::Symbol, hir::Type)>>,
     edition: Edition,
 ) -> Option<HoverAction> {
     let mut targets: Vec<hir::ModuleDef> = Vec::new();
@@ -554,6 +569,12 @@ fn goto_type_action_for_def(
         walk_and_push_ty(db, &ty, &mut push_new_def);
     }
 
+    if let Some(subst_types) = subst_types {
+        for (_, ty) in subst_types {
+            walk_and_push_ty(db, &ty, &mut push_new_def);
+        }
+    }
+
     HoverAction::goto_type_from_targets(db, targets, edition)
 }
 
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 e617d462ecd..8fbd445d962 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
@@ -5,7 +5,7 @@ use either::Either;
 use hir::{
     db::ExpandDatabase, Adt, AsAssocItem, AsExternAssocItem, AssocItemContainer, CaptureKind,
     DynCompatibilityViolation, HasCrate, HasSource, HirDisplay, Layout, LayoutError,
-    MethodViolationCode, Name, Semantics, Trait, Type, TypeInfo,
+    MethodViolationCode, Name, Semantics, Symbol, Trait, Type, TypeInfo, VariantDef,
 };
 use ide_db::{
     base_db::SourceDatabase,
@@ -27,7 +27,7 @@ use syntax::{algo, ast, match_ast, AstNode, AstToken, Direction, SyntaxToken, T}
 
 use crate::{
     doc_links::{remove_links, rewrite_links},
-    hover::{notable_traits, walk_and_push_ty},
+    hover::{notable_traits, walk_and_push_ty, SubstTyLen},
     interpret::render_const_eval_error,
     HoverAction, HoverConfig, HoverResult, Markup, MemoryLayoutHoverConfig,
     MemoryLayoutHoverRenderKind,
@@ -274,7 +274,7 @@ pub(super) fn keyword(
     let markup = process_markup(
         sema.db,
         Definition::Module(doc_owner),
-        &markup(Some(docs.into()), description, None, None),
+        &markup(Some(docs.into()), description, None, None, String::new()),
         config,
     );
     Some(HoverResult { markup, actions })
@@ -336,8 +336,8 @@ pub(super) fn try_for_lint(attr: &ast::Attr, token: &SyntaxToken) -> Option<Hove
                 .and_then(|t| algo::non_trivia_sibling(t, Direction::Prev))
                 .filter(|t| t.kind() == T![:])
                 .and_then(|t| algo::non_trivia_sibling(t, Direction::Prev))
-                .map_or(false, |t| {
-                    t.kind() == T![ident] && t.into_token().map_or(false, |t| t.text() == "clippy")
+                .is_some_and(|t| {
+                    t.kind() == T![ident] && t.into_token().is_some_and(|t| t.text() == "clippy")
                 });
             if is_clippy {
                 (true, CLIPPY_LINTS)
@@ -378,7 +378,18 @@ pub(super) fn process_markup(
 
 fn definition_owner_name(db: &RootDatabase, def: &Definition, edition: Edition) -> Option<String> {
     match def {
-        Definition::Field(f) => Some(f.parent_def(db).name(db)),
+        Definition::Field(f) => {
+            let parent = f.parent_def(db);
+            let parent_name = parent.name(db);
+            let parent_name = parent_name.display(db, edition).to_string();
+            return match parent {
+                VariantDef::Variant(variant) => {
+                    let enum_name = variant.parent_enum(db).name(db);
+                    Some(format!("{}::{parent_name}", enum_name.display(db, edition)))
+                }
+                _ => Some(parent_name),
+            };
+        }
         Definition::Local(l) => l.parent(db).name(db),
         Definition::Variant(e) => Some(e.parent_enum(db).name(db)),
 
@@ -421,6 +432,7 @@ pub(super) fn definition(
     notable_traits: &[(Trait, Vec<(Option<Type>, Name)>)],
     macro_arm: Option<u32>,
     hovered_definition: bool,
+    subst_types: Option<&Vec<(Symbol, Type)>>,
     config: &HoverConfig,
     edition: Edition,
 ) -> Markup {
@@ -582,12 +594,21 @@ pub(super) fn definition(
         _ => None,
     };
 
+    let variance_info = || match def {
+        Definition::GenericParam(it) => it.variance(db).as_ref().map(ToString::to_string),
+        _ => None,
+    };
+
     let mut extra = String::new();
     if hovered_definition {
         if let Some(notable_traits) = render_notable_trait(db, notable_traits, edition) {
             extra.push_str("\n___\n");
             extra.push_str(&notable_traits);
         }
+        if let Some(variance_info) = variance_info() {
+            extra.push_str("\n___\n");
+            extra.push_str(&variance_info);
+        }
         if let Some(layout_info) = layout_info() {
             extra.push_str("\n___\n");
             extra.push_str(&layout_info);
@@ -604,7 +625,38 @@ pub(super) fn definition(
         desc.push_str(&value);
     }
 
-    markup(docs.map(Into::into), desc, extra.is_empty().not().then_some(extra), mod_path)
+    let subst_types = match config.max_subst_ty_len {
+        SubstTyLen::Hide => String::new(),
+        SubstTyLen::LimitTo(_) | SubstTyLen::Unlimited => {
+            let limit = if let SubstTyLen::LimitTo(limit) = config.max_subst_ty_len {
+                Some(limit)
+            } else {
+                None
+            };
+            subst_types
+                .map(|subst_type| {
+                    subst_type
+                        .iter()
+                        .filter(|(_, ty)| !ty.is_unknown())
+                        .format_with(", ", |(name, ty), fmt| {
+                            fmt(&format_args!(
+                                "`{name}` = `{}`",
+                                ty.display_truncated(db, limit, edition)
+                            ))
+                        })
+                        .to_string()
+                })
+                .unwrap_or_default()
+        }
+    };
+
+    markup(
+        docs.map(Into::into),
+        desc,
+        extra.is_empty().not().then_some(extra),
+        mod_path,
+        subst_types,
+    )
 }
 
 pub(super) fn literal(
@@ -663,10 +715,22 @@ pub(super) fn literal(
     let mut s = format!("```rust\n{ty}\n```\n___\n\n");
     match value {
         Ok(value) => {
+            let backtick_len = value.chars().filter(|c| *c == '`').count();
+            let spaces_len = value.chars().filter(|c| *c == ' ').count();
+            let backticks = "`".repeat(backtick_len + 1);
+            let space_char = if spaces_len == value.len() { "" } else { " " };
+
             if let Some(newline) = value.find('\n') {
-                format_to!(s, "value of literal (truncated up to newline): {}", &value[..newline])
+                format_to!(
+                    s,
+                    "value of literal (truncated up to newline): {backticks}{space_char}{}{space_char}{backticks}",
+                    &value[..newline]
+                )
             } else {
-                format_to!(s, "value of literal: {value}")
+                format_to!(
+                    s,
+                    "value of literal: {backticks}{space_char}{value}{space_char}{backticks}"
+                )
             }
         }
         Err(error) => format_to!(s, "invalid literal: {error}"),
@@ -831,12 +895,11 @@ fn closure_ty(
     } else {
         String::new()
     };
-    let mut markup = format!("```rust\n{}", c.display_with_id(sema.db, edition));
+    let mut markup = format!("```rust\n{}\n```", c.display_with_impl(sema.db, edition));
 
     if let Some(trait_) = c.fn_trait(sema.db).get_id(sema.db, original.krate(sema.db).into()) {
         push_new_def(hir::Trait::from(trait_).into())
     }
-    format_to!(markup, "\n{}\n```", c.display_with_impl(sema.db, edition),);
     if let Some(layout) =
         render_memory_layout(config.memory_layout, || original.layout(sema.db), |_| None, |_| None)
     {
@@ -872,6 +935,7 @@ fn markup(
     rust: String,
     extra: Option<String>,
     mod_path: Option<String>,
+    subst_types: String,
 ) -> Markup {
     let mut buf = String::new();
 
@@ -886,6 +950,10 @@ fn markup(
         buf.push_str(&extra);
     }
 
+    if !subst_types.is_empty() {
+        format_to!(buf, "\n___\n{subst_types}");
+    }
+
     if let Some(doc) = docs {
         format_to!(buf, "\n___\n\n{}", doc);
     }
@@ -901,7 +969,7 @@ fn find_std_module(
     let std_crate = famous_defs.std()?;
     let std_root_module = std_crate.root_module();
     std_root_module.children(db).find(|module| {
-        module.name(db).map_or(false, |module| module.display(db, edition).to_string() == name)
+        module.name(db).is_some_and(|module| module.display(db, edition).to_string() == name)
     })
 }
 
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 50d0d4c5df6..2e7637e4677 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
@@ -20,6 +20,7 @@ const HOVER_BASE_CONFIG: HoverConfig = HoverConfig {
     max_trait_assoc_items_count: None,
     max_fields_count: Some(5),
     max_enum_variants_count: Some(5),
+    max_subst_ty_len: super::SubstTyLen::Unlimited,
 };
 
 fn check_hover_no_result(ra_fixture: &str) {
@@ -347,7 +348,6 @@ fn main() {
         expect![[r#"
             *|*
             ```rust
-            {closure#0}
             impl Fn(i32) -> i32
             ```
             ___
@@ -371,7 +371,6 @@ fn main() {
         expect![[r#"
             *|*
             ```rust
-            {closure#0}
             impl Fn(i32) -> i32
             ```
             ___
@@ -406,7 +405,6 @@ fn main() {
         expect![[r#"
             *|*
             ```rust
-            {closure#0}
             impl FnOnce()
             ```
             ___
@@ -436,7 +434,6 @@ fn main() {
         expect![[r#"
             *|*
             ```rust
-            {closure#0}
             impl FnMut()
             ```
             ___
@@ -462,7 +459,6 @@ fn main() {
 "#,
         expect![[r#"
             ```rust
-            {closure#0}
             impl FnOnce() -> S2
             ```
             ___
@@ -2322,6 +2318,53 @@ fn foo(Foo { b$0ar }: &Foo) {}
 }
 
 #[test]
+fn test_hover_show_type_def_for_subst() {
+    check_actions(
+        r#"
+fn f<T>(t: T) {
+
+}
+
+struct S;
+
+fn test() {
+    let a = S;
+    f$0(a);
+}
+"#,
+        expect![[r#"
+            [
+                Reference(
+                    FilePositionWrapper {
+                        file_id: FileId(
+                            0,
+                        ),
+                        offset: 3,
+                    },
+                ),
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "ra_test_fixture::S",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 20..29,
+                                focus_range: 27..28,
+                                name: "S",
+                                kind: Struct,
+                                description: "struct S",
+                            },
+                        },
+                    ],
+                ),
+            ]
+        "#]],
+    );
+}
+
+#[test]
 fn test_hover_non_ascii_space_doc() {
     check(
         "
@@ -2969,7 +3012,6 @@ fn main() {
         expect![[r#"
             *|*
             ```rust
-            {closure#0}
             impl Fn(i32) -> i32
             ```
 
@@ -3212,6 +3254,11 @@ fn foo_$0test() {}
                             },
                         },
                         cfg: None,
+                        update_test: UpdateTest {
+                            expect_test: false,
+                            insta: false,
+                            snapbox: false,
+                        },
                     },
                 ),
             ]
@@ -3229,28 +3276,33 @@ mod tests$0 {
 }
 "#,
         expect![[r#"
-                [
-                    Runnable(
-                        Runnable {
-                            use_name_in_title: false,
-                            nav: NavigationTarget {
-                                file_id: FileId(
-                                    0,
-                                ),
-                                full_range: 0..46,
-                                focus_range: 4..9,
-                                name: "tests",
-                                kind: Module,
-                                description: "mod tests",
-                            },
-                            kind: TestMod {
-                                path: "tests",
-                            },
-                            cfg: None,
+            [
+                Runnable(
+                    Runnable {
+                        use_name_in_title: false,
+                        nav: NavigationTarget {
+                            file_id: FileId(
+                                0,
+                            ),
+                            full_range: 0..46,
+                            focus_range: 4..9,
+                            name: "tests",
+                            kind: Module,
+                            description: "mod tests",
                         },
-                    ),
-                ]
-            "#]],
+                        kind: TestMod {
+                            path: "tests",
+                        },
+                        cfg: None,
+                        update_test: UpdateTest {
+                            expect_test: false,
+                            insta: false,
+                            snapbox: false,
+                        },
+                    },
+                ),
+            ]
+        "#]],
     );
 }
 
@@ -4720,7 +4772,7 @@ fn hover_type_param_sized_bounds() {
 //- minicore: sized
 trait Trait {}
 struct Foo<T>(T);
-impl<T: Trait> Foo<T$0> {}
+impl<T$0: Trait> Foo<T> {}
 "#,
         expect![[r#"
             *T*
@@ -4735,7 +4787,7 @@ impl<T: Trait> Foo<T$0> {}
 //- minicore: sized
 trait Trait {}
 struct Foo<T>(T);
-impl<T: Trait + ?Sized> Foo<T$0> {}
+impl<T$0: Trait + ?Sized> Foo<T> {}
 "#,
         expect![[r#"
             *T*
@@ -4763,6 +4815,10 @@ fn foo<T$0>() {}
                 ```rust
                 T
                 ```
+
+                ---
+
+                invariant
             "#]],
         );
     }
@@ -4780,6 +4836,10 @@ fn foo<T$0: Sized>() {}
                 ```rust
                 T
                 ```
+
+                ---
+
+                invariant
             "#]],
         );
     }
@@ -4797,6 +4857,10 @@ fn foo<T$0: ?Sized>() {}
                 ```rust
                 T: ?Sized
                 ```
+
+                ---
+
+                invariant
             "#]],
         );
     }
@@ -4815,6 +4879,10 @@ fn foo<T$0: Trait>() {}
                 ```rust
                 T: Trait
                 ```
+
+                ---
+
+                invariant
             "#]],
         );
     }
@@ -4833,6 +4901,10 @@ fn foo<T$0: Trait + Sized>() {}
                 ```rust
                 T: Trait
                 ```
+
+                ---
+
+                invariant
             "#]],
         );
     }
@@ -4851,6 +4923,10 @@ fn foo<T$0: Trait + ?Sized>() {}
                 ```rust
                 T: Trait + ?Sized
                 ```
+
+                ---
+
+                invariant
             "#]],
         );
     }
@@ -4868,6 +4944,10 @@ fn foo<T$0: ?Sized + Sized + Sized>() {}
                 ```rust
                 T
                 ```
+
+                ---
+
+                invariant
             "#]],
         );
     }
@@ -4886,6 +4966,10 @@ fn foo<T$0: Sized + ?Sized + Sized + Trait>() {}
                 ```rust
                 T: Trait
                 ```
+
+                ---
+
+                invariant
             "#]],
         );
     }
@@ -5176,6 +5260,10 @@ fn main() {
 
             ---
 
+            `Self` = `()`
+
+            ---
+
             false
         "#]],
     );
@@ -5208,6 +5296,10 @@ fn main() {
 
             ---
 
+            `Self` = `i32`
+
+            ---
+
             false
         "#]],
     );
@@ -7285,7 +7377,7 @@ enum Enum {
             *field*
 
             ```rust
-            ra_test_fixture::RecordV
+            ra_test_fixture::Enum::RecordV
             ```
 
             ```rust
@@ -8116,7 +8208,7 @@ fn main() {
             ```
             ___
 
-            value of literal: 🦀🦀\A
+            value of literal: ` 🦀🦀\A `
         "#]],
     );
     check(
@@ -8132,7 +8224,7 @@ fn main() {
             ```
             ___
 
-            value of literal: 🦀\u{1f980}\\\x41
+            value of literal: ` 🦀\u{1f980}\\\x41 `
         "#]],
     );
     check(
@@ -8154,7 +8246,7 @@ fsdghs";
             ```
             ___
 
-            value of literal (truncated up to newline): 🦀\u{1f980}\\\x41
+            value of literal (truncated up to newline): ` 🦀\u{1f980}\\\x41 `
         "#]],
     );
 }
@@ -8174,9 +8266,74 @@ fn main() {
             ```
             ___
 
-            value of literal: 🦀🦀\A
+            value of literal: ` 🦀🦀\A `
+        "#]],
+    );
+}
+
+#[test]
+fn rawstring_literal() {
+    check(
+        r#"
+fn main() {
+    $0r"`[^`]*`";
+}"#,
+        expect![[r#"
+            *r"`[^`]*`"*
+            ```rust
+            &str
+            ```
+            ___
+
+            value of literal: ```` `[^`]*` ````
+        "#]],
+    );
+    check(
+        r#"
+fn main() {
+    $0r"`";
+}"#,
+        expect![[r#"
+            *r"`"*
+            ```rust
+            &str
+            ```
+            ___
+
+            value of literal: `` ` ``
+        "#]],
+    );
+    check(
+        r#"
+fn main() {
+    $0r"    ";
+}"#,
+        expect![[r#"
+            *r"    "*
+            ```rust
+            &str
+            ```
+            ___
+
+            value of literal: `    `
         "#]],
     );
+    check(
+        r#"
+fn main() {
+    $0r" Hello World ";
+
+}"#,
+        expect![[r#"
+            *r" Hello World "*
+            ```rust
+            &str
+            ```
+            ___
+
+            value of literal: `  Hello World  `
+"#]],
+    )
 }
 
 #[test]
@@ -8194,7 +8351,7 @@ fn main() {
             ```
             ___
 
-            value of literal: [240, 159, 166, 128, 92]
+            value of literal: ` [240, 159, 166, 128, 92] `
         "#]],
     );
     check(
@@ -8210,7 +8367,7 @@ fn main() {
             ```
             ___
 
-            value of literal: [92, 120, 70, 48, 92, 120, 57, 70, 92, 120, 65, 54, 92, 120, 56, 48, 92, 92]
+            value of literal: ` [92, 120, 70, 48, 92, 120, 57, 70, 92, 120, 65, 54, 92, 120, 56, 48, 92, 92] `
         "#]],
     );
 }
@@ -8230,7 +8387,7 @@ fn main() {
             ```
             ___
 
-            value of literal: 0xF0
+            value of literal: ` 0xF0 `
         "#]],
     );
     check(
@@ -8246,7 +8403,7 @@ fn main() {
             ```
             ___
 
-            value of literal: 0x5C
+            value of literal: ` 0x5C `
         "#]],
     );
 }
@@ -8266,7 +8423,7 @@ fn main() {
             ```
             ___
 
-            value of literal: A
+            value of literal: ` A `
         "#]],
     );
     check(
@@ -8282,7 +8439,7 @@ fn main() {
             ```
             ___
 
-            value of literal: \
+            value of literal: ` \ `
         "#]],
     );
     check(
@@ -8298,7 +8455,7 @@ fn main() {
             ```
             ___
 
-            value of literal: 🦀
+            value of literal: ` 🦀 `
         "#]],
     );
 }
@@ -8318,7 +8475,7 @@ fn main() {
             ```
             ___
 
-            value of literal: 1 (bits: 0x3FF0000000000000)
+            value of literal: ` 1 (bits: 0x3FF0000000000000) `
         "#]],
     );
     check(
@@ -8334,7 +8491,7 @@ fn main() {
             ```
             ___
 
-            value of literal: 1 (bits: 0x3C00)
+            value of literal: ` 1 (bits: 0x3C00) `
         "#]],
     );
     check(
@@ -8350,7 +8507,7 @@ fn main() {
             ```
             ___
 
-            value of literal: 1 (bits: 0x3F800000)
+            value of literal: ` 1 (bits: 0x3F800000) `
         "#]],
     );
     check(
@@ -8366,7 +8523,7 @@ fn main() {
             ```
             ___
 
-            value of literal: 1 (bits: 0x3FFF0000000000000000000000000000)
+            value of literal: ` 1 (bits: 0x3FFF0000000000000000000000000000) `
         "#]],
     );
     check(
@@ -8382,7 +8539,7 @@ fn main() {
             ```
             ___
 
-            value of literal: 134000000000000 (bits: 0x42DE77D399980000)
+            value of literal: ` 134000000000000 (bits: 0x42DE77D399980000) `
         "#]],
     );
     check(
@@ -8398,7 +8555,7 @@ fn main() {
             ```
             ___
 
-            value of literal: 1523527134274733600000000 (bits: 0x44F429E9249F629B)
+            value of literal: ` 1523527134274733600000000 (bits: 0x44F429E9249F629B) `
         "#]],
     );
     check(
@@ -8434,7 +8591,7 @@ fn main() {
             ```
             ___
 
-            value of literal: 34325236457856836345234 (0x744C659178614489D92|0b111010001001100011001011001000101111000011000010100010010001001110110010010)
+            value of literal: ` 34325236457856836345234 (0x744C659178614489D92|0b111010001001100011001011001000101111000011000010100010010001001110110010010) `
         "#]],
     );
     check(
@@ -8450,7 +8607,7 @@ fn main() {
             ```
             ___
 
-            value of literal: 13412342421 (0x31F701A95|0b1100011111011100000001101010010101)
+            value of literal: ` 13412342421 (0x31F701A95|0b1100011111011100000001101010010101) `
         "#]],
     );
     check(
@@ -8466,7 +8623,7 @@ fn main() {
             ```
             ___
 
-            value of literal: 306328611 (0x12423423|0b10010010000100011010000100011)
+            value of literal: ` 306328611 (0x12423423|0b10010010000100011010000100011) `
         "#]],
     );
     check(
@@ -8482,7 +8639,7 @@ fn main() {
             ```
             ___
 
-            value of literal: 255 (0xFF|0b11111111)
+            value of literal: ` 255 (0xFF|0b11111111) `
         "#]],
     );
     check(
@@ -8498,7 +8655,7 @@ fn main() {
             ```
             ___
 
-            value of literal: 5349 (0x14E5|0b1010011100101)
+            value of literal: ` 5349 (0x14E5|0b1010011100101) `
         "#]],
     );
     check(
@@ -9501,3 +9658,539 @@ fn main() {
         "#]],
     );
 }
+
+#[test]
+fn subst_fn() {
+    check(
+        r#"
+struct Foo<T>(T);
+impl<T> Foo<T> {
+    fn foo<U>(v: T, u: U) {}
+}
+
+fn bar() {
+    Foo::fo$0o(123, false);
+}
+        "#,
+        expect![[r#"
+            *foo*
+
+            ```rust
+            ra_test_fixture::Foo
+            ```
+
+            ```rust
+            impl<T> Foo<T>
+            fn foo<U>(v: T, u: U)
+            ```
+
+            ---
+
+            `T` = `i32`, `U` = `bool`
+        "#]],
+    );
+    check(
+        r#"
+fn foo<T>(v: T) {}
+
+fn bar() {
+    fo$0o(123);
+}
+        "#,
+        expect![[r#"
+            *foo*
+
+            ```rust
+            ra_test_fixture
+            ```
+
+            ```rust
+            fn foo<T>(v: T)
+            ```
+
+            ---
+
+            `T` = `i32`
+        "#]],
+    );
+}
+
+#[test]
+fn subst_record_constructor() {
+    check(
+        r#"
+struct Foo<T> { field: T }
+
+fn bar() {
+    let v = $0Foo { field: 123 };
+}
+        "#,
+        expect![[r#"
+            *Foo*
+
+            ```rust
+            ra_test_fixture
+            ```
+
+            ```rust
+            struct Foo<T> {
+                field: T,
+            }
+            ```
+
+            ---
+
+            `T` = `i32`
+        "#]],
+    );
+    check(
+        r#"
+struct Foo<T> { field: T }
+
+fn bar() {
+    let v = Foo { field: 123 };
+    let $0Foo { field: _ } = v;
+}
+        "#,
+        expect![[r#"
+            *Foo*
+
+            ```rust
+            ra_test_fixture
+            ```
+
+            ```rust
+            struct Foo<T> {
+                field: T,
+            }
+            ```
+
+            ---
+
+            `T` = `i32`
+        "#]],
+    );
+}
+
+#[test]
+fn subst_method_call() {
+    check(
+        r#"
+struct Foo<T>(T);
+
+impl<U> Foo<U> {
+    fn bar<T>(self, v: T) {}
+}
+
+fn baz() {
+    Foo(123).bar$0("hello");
+}
+    "#,
+        expect![[r#"
+            *bar*
+
+            ```rust
+            ra_test_fixture::Foo
+            ```
+
+            ```rust
+            impl<U> Foo<U>
+            fn bar<T>(self, v: T)
+            ```
+
+            ---
+
+            `U` = `i32`, `T` = `&str`
+        "#]],
+    );
+}
+
+#[test]
+fn subst_type_alias_do_not_work() {
+    // It is very hard to support subst for type aliases properly in all places because they are eagerly evaluated.
+    // We can show the user the subst for the underlying type instead but that'll be very confusing.
+    check(
+        r#"
+struct Foo<T, U> { a: T, b: U }
+type Alias<T> = Foo<T, i32>;
+
+fn foo() {
+    let _ = Alias$0 { a: true, b: 123 };
+}
+    "#,
+        expect![[r#"
+            *Alias*
+
+            ```rust
+            ra_test_fixture
+            ```
+
+            ```rust
+            type Alias<T> = Foo<T, i32>
+            ```
+        "#]],
+    );
+}
+
+#[test]
+fn subst_self() {
+    check(
+        r#"
+trait Trait<T> {
+    fn foo<U>(&self, v: U) {}
+}
+struct Struct<T>(T);
+impl<T> Trait<i64> for Struct<T> {}
+
+fn bar() {
+    Struct(123).foo$0(true);
+}
+    "#,
+        expect![[r#"
+            *foo*
+
+            ```rust
+            ra_test_fixture::Trait
+            ```
+
+            ```rust
+            trait Trait<T>
+            fn foo<U>(&self, v: U)
+            ```
+
+            ---
+
+            `Self` = `Struct<i32>`, `T` = `i64`, `U` = `bool`
+        "#]],
+    );
+}
+
+#[test]
+fn subst_with_lifetimes_and_consts() {
+    check(
+        r#"
+struct Foo<'a, const N: usize, T>(&[T; N]);
+
+impl<'a, T, const N: usize> Foo<'a, N, T> {
+    fn foo<'b, const Z: u32, U>(&self, v: U) {}
+}
+
+fn bar() {
+    Foo(&[1i8]).fo$0o::<456, _>("");
+}
+    "#,
+        expect![[r#"
+            *foo*
+
+            ```rust
+            ra_test_fixture::Foo
+            ```
+
+            ```rust
+            impl<'a, T, const N: usize> Foo<'a, N, T>
+            fn foo<'b, const Z: u32, U>(&self, v: U)
+            ```
+
+            ---
+
+            `T` = `i8`, `U` = `&str`
+        "#]],
+    );
+}
+
+#[test]
+fn subst_field() {
+    check(
+        r#"
+struct Foo<T> { field: T }
+
+fn bar() {
+    let v = Foo { $0field: 123 };
+}
+    "#,
+        expect![[r#"
+            *field*
+
+            ```rust
+            ra_test_fixture::Foo
+            ```
+
+            ```rust
+            field: T
+            ```
+
+            ---
+
+            `T` = `i32`
+        "#]],
+    );
+    check(
+        r#"
+struct Foo<T> { field: T }
+
+fn bar() {
+    let field = 123;
+    let v = Foo { field$0 };
+}
+    "#,
+        expect![[r#"
+            *field*
+
+            ```rust
+            let field: i32
+            ```
+            ---
+
+            ```rust
+            ra_test_fixture::Foo
+            ```
+
+            ```rust
+            field: T
+            ```
+
+            ---
+
+            `T` = `i32`
+        "#]],
+    );
+    check(
+        r#"
+struct Foo<T> { field: T }
+
+fn bar() {
+    let v = Foo { field: 123 };
+    let Foo { field$0 } = v;
+}
+    "#,
+        expect![[r#"
+            *field*
+
+            ```rust
+            let field: i32
+            ```
+
+            ---
+
+            size = 4, align = 4
+            ---
+
+            ```rust
+            ra_test_fixture::Foo
+            ```
+
+            ```rust
+            field: T
+            ```
+
+            ---
+
+            `T` = `i32`
+        "#]],
+    );
+    check(
+        r#"
+struct Foo<T> { field: T }
+
+fn bar() {
+    let v = Foo { field: 123 };
+    let Foo { field$0: _ } = v;
+}
+    "#,
+        expect![[r#"
+            *field*
+
+            ```rust
+            ra_test_fixture::Foo
+            ```
+
+            ```rust
+            field: T
+            ```
+
+            ---
+
+            `T` = `i32`
+        "#]],
+    );
+    check(
+        r#"
+struct Foo<T> { field: T }
+
+fn bar() {
+    let v = Foo { field: 123 };
+    let _ = (&v).$0field;
+}
+    "#,
+        expect![[r#"
+            *field*
+
+            ```rust
+            ra_test_fixture::Foo
+            ```
+
+            ```rust
+            field: T
+            ```
+
+            ---
+
+            `T` = `i32`
+        "#]],
+    );
+    check(
+        r#"
+struct Foo<T>(T);
+
+fn bar() {
+    let v = Foo(123);
+    let _ = v.$00;
+}
+    "#,
+        expect![[r#"
+            *0*
+
+            ```rust
+            ra_test_fixture::Foo
+            ```
+
+            ```rust
+            0: T
+            ```
+
+            ---
+
+            `T` = `i32`
+        "#]],
+    );
+}
+
+#[test]
+fn i128_max() {
+    check(
+        r#"
+//- /core.rs library crate:core
+#![rustc_coherence_is_core]
+impl u128 {
+    pub const MAX: Self = 340_282_366_920_938_463_463_374_607_431_768_211_455u128;
+}
+impl i128 {
+    pub const MAX: Self = (u128::MAX >> 1) as Self;
+}
+
+//- /foo.rs crate:foo deps:core
+fn foo() {
+    let _ = i128::MAX$0;
+}
+        "#,
+        expect![
+            r#"
+            *MAX*
+
+            ```rust
+            core
+            ```
+
+            ```rust
+            pub const MAX: Self = 170141183460469231731687303715884105727 (0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
+            ```
+        "#
+        ],
+    );
+}
+
+#[test]
+fn test_runnables_with_snapshot_tests() {
+    check_actions(
+        r#"
+//- /lib.rs crate:foo deps:expect_test,insta,snapbox
+use expect_test::expect;
+use insta::assert_debug_snapshot;
+use snapbox::Assert;
+
+#[test]
+fn test$0() {
+    let actual = "new25";
+    expect!["new25"].assert_eq(&actual);
+    Assert::new()
+        .action_env("SNAPSHOTS")
+        .eq(actual, snapbox::str!["new25"]);
+    assert_debug_snapshot!(actual);
+}
+
+//- /lib.rs crate:expect_test
+struct Expect;
+
+impl Expect {
+    fn assert_eq(&self, actual: &str) {}
+}
+
+#[macro_export]
+macro_rules! expect {
+    ($e:expr) => Expect; // dummy
+}
+
+//- /lib.rs crate:insta
+#[macro_export]
+macro_rules! assert_debug_snapshot {
+    ($e:expr) => {}; // dummy
+}
+
+//- /lib.rs crate:snapbox
+pub struct Assert;
+
+impl Assert {
+    pub fn new() -> Self { Assert }
+
+    pub fn action_env(&self, env: &str) -> &Self { self }
+
+    pub fn eq(&self, actual: &str, expected: &str) {}
+}
+
+#[macro_export]
+macro_rules! str {
+    ($e:expr) => ""; // dummy
+}
+        "#,
+        expect![[r#"
+            [
+                Reference(
+                    FilePositionWrapper {
+                        file_id: FileId(
+                            0,
+                        ),
+                        offset: 92,
+                    },
+                ),
+                Runnable(
+                    Runnable {
+                        use_name_in_title: false,
+                        nav: NavigationTarget {
+                            file_id: FileId(
+                                0,
+                            ),
+                            full_range: 81..301,
+                            focus_range: 92..96,
+                            name: "test",
+                            kind: Function,
+                        },
+                        kind: Test {
+                            test_id: Path(
+                                "test",
+                            ),
+                            attr: TestAttr {
+                                ignore: false,
+                            },
+                        },
+                        cfg: None,
+                        update_test: UpdateTest {
+                            expect_test: true,
+                            insta: true,
+                            snapbox: true,
+                        },
+                    },
+                ),
+            ]
+        "#]],
+    );
+}
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 aa99ba49bc8..faa65019eea 100644
--- a/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/inlay_hints.rs
@@ -856,4 +856,18 @@ fn main() {
 }"#,
         );
     }
+
+    #[test]
+    fn regression_18840() {
+        check(
+            r#"
+//- proc_macros: issue_18840
+#[proc_macros::issue_18840]
+fn foo() {
+    let
+    loop {}
+}
+"#,
+        );
+    }
 }
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 4d7d6e270e0..4e48baa6f14 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
@@ -313,7 +313,7 @@ fn needs_parens_for_adjustment_hints(expr: &ast::Expr, postfix: bool) -> (bool,
     // - `dummy_expr` is the original expression wrapped in the operator we want (`*`/`.*`)
     // - `expr`       is the clone of the original expression (with `dummy_expr` as the parent)
 
-    let needs_outer_parens = parent.map_or(false, |p| dummy_expr.needs_parens_in(p));
+    let needs_outer_parens = parent.is_some_and(|p| dummy_expr.needs_parens_in(p));
     let needs_inner_parens = expr.needs_parens_in(dummy_expr.syntax().clone());
 
     (needs_outer_parens, needs_inner_parens)
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 cfe8657fd05..5afb98cb1c7 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
@@ -61,7 +61,6 @@ pub(super) fn hints(
         }
         hint.label.append_str(r);
     });
-    hint.pad_right = was_mut_last;
     let acc_base = acc.len();
     match pat {
         ast::Pat::IdentPat(pat) if pat.ref_token().is_none() && pat.mut_token().is_none() => {
@@ -86,6 +85,7 @@ pub(super) fn hints(
         }
         ast::Pat::OrPat(pat) if !pattern_adjustments.is_empty() && outer_paren_pat.is_none() => {
             hint.label.append_str("(");
+            was_mut_last = false;
             acc.push(InlayHint::closing_paren_after(
                 InlayKind::BindingMode,
                 pat.syntax().text_range(),
@@ -94,6 +94,7 @@ pub(super) fn hints(
         _ => (),
     }
     if !hint.label.parts.is_empty() {
+        hint.pad_right = was_mut_last;
         acc.push(hint);
     }
 
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 cd77c3ec3e9..8f2949cb387 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
@@ -32,7 +32,7 @@ pub(super) fn enum_hints(
         return None;
     }
     // data carrying enums without a primitive repr have no stable discriminants
-    if data_carrying && def.repr(sema.db).map_or(true, |r| r.int.is_none()) {
+    if data_carrying && def.repr(sema.db).is_none_or(|r| r.int.is_none()) {
         return None;
     }
     for variant in enum_.variant_list()?.variants() {
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 28b0fa6dd4d..a03ff6a52b4 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
@@ -153,7 +153,7 @@ fn is_param_name_suffix_of_fn_name(
                     .len()
                     .checked_sub(param_name.len())
                     .and_then(|at| function.is_char_boundary(at).then(|| function.split_at(at)))
-                    .map_or(false, |(prefix, suffix)| {
+                    .is_some_and(|(prefix, suffix)| {
                         suffix.eq_ignore_ascii_case(param_name) && prefix.ends_with('_')
                     })
         }
diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs
index c13fc843568..6e7c718953c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs
@@ -86,7 +86,7 @@ pub use crate::{
     highlight_related::{HighlightRelatedConfig, HighlightedRange},
     hover::{
         HoverAction, HoverConfig, HoverDocFormat, HoverGotoTypeData, HoverResult,
-        MemoryLayoutHoverConfig, MemoryLayoutHoverRenderKind,
+        MemoryLayoutHoverConfig, MemoryLayoutHoverRenderKind, SubstTyLen,
     },
     inlay_hints::{
         AdjustmentHints, AdjustmentHintsMode, ClosureReturnTypeHints, DiscriminantHints,
@@ -96,8 +96,8 @@ pub use crate::{
     join_lines::JoinLinesConfig,
     markup::Markup,
     moniker::{
-        MonikerDescriptorKind, MonikerKind, MonikerResult, PackageInformation,
-        SymbolInformationKind,
+        Moniker, MonikerDescriptorKind, MonikerIdentifier, MonikerKind, MonikerResult,
+        PackageInformation, SymbolInformationKind,
     },
     move_item::Direction,
     navigation_target::{NavigationTarget, TryToNav, UpmappingResult},
@@ -671,19 +671,17 @@ impl Analysis {
     /// Computes completions at the given position.
     pub fn completions(
         &self,
-        config: &CompletionConfig,
+        config: &CompletionConfig<'_>,
         position: FilePosition,
         trigger_character: Option<char>,
     ) -> Cancellable<Option<Vec<CompletionItem>>> {
-        self.with_db(|db| {
-            ide_completion::completions(db, config, position, trigger_character).map(Into::into)
-        })
+        self.with_db(|db| ide_completion::completions(db, config, position, trigger_character))
     }
 
     /// Resolves additional completion data at the position given.
     pub fn resolve_completion_edits(
         &self,
-        config: &CompletionConfig,
+        config: &CompletionConfig<'_>,
         position: FilePosition,
         imports: impl IntoIterator<Item = (String, String)> + std::panic::UnwindSafe,
     ) -> Cancellable<Vec<TextEdit>> {
diff --git a/src/tools/rust-analyzer/crates/ide/src/moniker.rs b/src/tools/rust-analyzer/crates/ide/src/moniker.rs
index 14781b21296..052466725fa 100644
--- a/src/tools/rust-analyzer/crates/ide/src/moniker.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/moniker.rs
@@ -3,7 +3,7 @@
 
 use core::fmt;
 
-use hir::{Adt, AsAssocItem, AssocItemContainer, Crate, MacroKind, Semantics};
+use hir::{Adt, AsAssocItem, Crate, HirDisplay, MacroKind, Semantics};
 use ide_db::{
     base_db::{CrateOrigin, LangCrateOrigin},
     defs::{Definition, IdentClass},
@@ -11,6 +11,7 @@ use ide_db::{
     FilePosition, RootDatabase,
 };
 use itertools::Itertools;
+use span::Edition;
 use syntax::{AstNode, SyntaxKind::*, T};
 
 use crate::{doc_links::token_as_doc_comment, parent_module::crates_for, RangeInfo};
@@ -57,8 +58,8 @@ pub enum SymbolInformationKind {
 impl From<SymbolInformationKind> for MonikerDescriptorKind {
     fn from(value: SymbolInformationKind) -> Self {
         match value {
-            SymbolInformationKind::AssociatedType => Self::TypeParameter,
-            SymbolInformationKind::Attribute => Self::Macro,
+            SymbolInformationKind::AssociatedType => Self::Type,
+            SymbolInformationKind::Attribute => Self::Meta,
             SymbolInformationKind::Constant => Self::Term,
             SymbolInformationKind::Enum => Self::Type,
             SymbolInformationKind::EnumMember => Self::Type,
@@ -70,7 +71,7 @@ impl From<SymbolInformationKind> for MonikerDescriptorKind {
             SymbolInformationKind::Parameter => Self::Parameter,
             SymbolInformationKind::SelfParameter => Self::Parameter,
             SymbolInformationKind::StaticMethod => Self::Method,
-            SymbolInformationKind::StaticVariable => Self::Meta,
+            SymbolInformationKind::StaticVariable => Self::Term,
             SymbolInformationKind::Struct => Self::Type,
             SymbolInformationKind::Trait => Self::Type,
             SymbolInformationKind::TraitMethod => Self::Method,
@@ -109,10 +110,12 @@ pub enum MonikerKind {
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub struct MonikerResult {
-    pub identifier: MonikerIdentifier,
-    pub kind: MonikerKind,
-    pub package_information: PackageInformation,
+pub enum MonikerResult {
+    /// Uniquely identifies a definition.
+    Moniker(Moniker),
+    /// Specifies that the definition is a local, and so does not have a unique identifier. Provides
+    /// a unique identifier for the container.
+    Local { enclosing_moniker: Option<Moniker> },
 }
 
 impl MonikerResult {
@@ -121,6 +124,15 @@ impl MonikerResult {
     }
 }
 
+/// Information which uniquely identifies a definition which might be referenceable outside of the
+/// source file. Visibility declarations do not affect presence.
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Moniker {
+    pub identifier: MonikerIdentifier,
+    pub kind: MonikerKind,
+    pub package_information: PackageInformation,
+}
+
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct PackageInformation {
     pub name: String,
@@ -232,157 +244,106 @@ pub(crate) fn def_to_kind(db: &RootDatabase, def: Definition) -> SymbolInformati
     }
 }
 
+/// Computes a `MonikerResult` for a definition. Result cases:
+///
+/// * `Some(MonikerResult::Moniker(_))` provides a unique `Moniker` which refers to a definition.
+///
+/// * `Some(MonikerResult::Local { .. })` provides a `Moniker` for the definition enclosing a local.
+///
+/// * `None` is returned for definitions which are not in a module: `BuiltinAttr`, `BuiltinType`,
+///   `BuiltinLifetime`, `TupleField`, `ToolModule`, and `InlineAsmRegOrRegClass`. TODO: it might be
+///   sensible to provide monikers that refer to some non-existent crate of compiler builtin
+///   definitions.
 pub(crate) fn def_to_moniker(
     db: &RootDatabase,
-    def: Definition,
+    definition: Definition,
     from_crate: Crate,
 ) -> Option<MonikerResult> {
-    if matches!(
-        def,
-        Definition::GenericParam(_)
-            | Definition::Label(_)
-            | Definition::DeriveHelper(_)
-            | Definition::BuiltinAttr(_)
-            | Definition::ToolModule(_)
-    ) {
-        return None;
+    match definition {
+        Definition::Local(_) | Definition::Label(_) | Definition::GenericParam(_) => {
+            return Some(MonikerResult::Local {
+                enclosing_moniker: enclosing_def_to_moniker(db, definition, from_crate),
+            });
+        }
+        _ => {}
     }
+    Some(MonikerResult::Moniker(def_to_non_local_moniker(db, definition, from_crate)?))
+}
 
-    let module = def.module(db)?;
+fn enclosing_def_to_moniker(
+    db: &RootDatabase,
+    mut def: Definition,
+    from_crate: Crate,
+) -> Option<Moniker> {
+    loop {
+        let enclosing_def = def.enclosing_definition(db)?;
+        if let Some(enclosing_moniker) = def_to_non_local_moniker(db, enclosing_def, from_crate) {
+            return Some(enclosing_moniker);
+        }
+        def = enclosing_def;
+    }
+}
+
+fn def_to_non_local_moniker(
+    db: &RootDatabase,
+    definition: Definition,
+    from_crate: Crate,
+) -> Option<Moniker> {
+    let module = definition.module(db)?;
     let krate = module.krate();
     let edition = krate.edition(db);
-    let mut description = vec![];
-    description.extend(module.path_to_root(db).into_iter().filter_map(|x| {
-        Some(MonikerDescriptor {
-            name: x.name(db)?.display(db, edition).to_string(),
-            desc: def_to_kind(db, x.into()).into(),
-        })
-    }));
-
-    // Handle associated items within a trait
-    if let Some(assoc) = def.as_assoc_item(db) {
-        let container = assoc.container(db);
-        match container {
-            AssocItemContainer::Trait(trait_) => {
-                // Because different traits can have functions with the same name,
-                // we have to include the trait name as part of the moniker for uniqueness.
-                description.push(MonikerDescriptor {
-                    name: trait_.name(db).display(db, edition).to_string(),
-                    desc: def_to_kind(db, trait_.into()).into(),
-                });
-            }
-            AssocItemContainer::Impl(impl_) => {
-                // Because a struct can implement multiple traits, for implementations
-                // we add both the struct name and the trait name to the path
-                if let Some(adt) = impl_.self_ty(db).as_adt() {
-                    description.push(MonikerDescriptor {
-                        name: adt.name(db).display(db, edition).to_string(),
-                        desc: def_to_kind(db, adt.into()).into(),
-                    });
-                }
 
-                if let Some(trait_) = impl_.trait_(db) {
-                    description.push(MonikerDescriptor {
-                        name: trait_.name(db).display(db, edition).to_string(),
-                        desc: def_to_kind(db, trait_.into()).into(),
+    // Add descriptors for this definition and every enclosing definition.
+    let mut reverse_description = vec![];
+    let mut def = definition;
+    loop {
+        match def {
+            Definition::SelfType(impl_) => {
+                if let Some(trait_ref) = impl_.trait_ref(db) {
+                    // Trait impls use the trait type for the 2nd parameter.
+                    reverse_description.push(MonikerDescriptor {
+                        name: display(db, edition, module, trait_ref),
+                        desc: MonikerDescriptorKind::TypeParameter,
                     });
                 }
-            }
-        }
-    }
-
-    if let Definition::Field(it) = def {
-        description.push(MonikerDescriptor {
-            name: it.parent_def(db).name(db).display(db, edition).to_string(),
-            desc: def_to_kind(db, it.parent_def(db).into()).into(),
-        });
-    }
-
-    // Qualify locals/parameters by their parent definition name.
-    if let Definition::Local(it) = def {
-        let parent = Definition::try_from(it.parent(db)).ok();
-        if let Some(parent) = parent {
-            let parent_name = parent.name(db);
-            if let Some(name) = parent_name {
-                description.push(MonikerDescriptor {
-                    name: name.display(db, edition).to_string(),
-                    desc: def_to_kind(db, parent).into(),
+                // Both inherent and trait impls use the self type for the first parameter.
+                reverse_description.push(MonikerDescriptor {
+                    name: display(db, edition, module, impl_.self_ty(db)),
+                    desc: MonikerDescriptorKind::TypeParameter,
+                });
+                reverse_description.push(MonikerDescriptor {
+                    name: "impl".to_owned(),
+                    desc: MonikerDescriptorKind::Type,
                 });
             }
-        }
-    }
-
-    let desc = def_to_kind(db, def).into();
-
-    let name_desc = match def {
-        // These are handled by top-level guard (for performance).
-        Definition::GenericParam(_)
-        | Definition::Label(_)
-        | Definition::DeriveHelper(_)
-        | Definition::BuiltinLifetime(_)
-        | Definition::BuiltinAttr(_)
-        | Definition::ToolModule(_)
-        | Definition::InlineAsmRegOrRegClass(_)
-        | Definition::InlineAsmOperand(_) => return None,
-
-        Definition::Local(local) => {
-            if !local.is_param(db) {
-                return None;
+            _ => {
+                if let Some(name) = def.name(db) {
+                    reverse_description.push(MonikerDescriptor {
+                        name: name.display(db, edition).to_string(),
+                        desc: def_to_kind(db, def).into(),
+                    });
+                } else if reverse_description.is_empty() {
+                    // Don't allow the last descriptor to be absent.
+                    return None;
+                } else {
+                    match def {
+                        Definition::Module(module) if module.is_crate_root() => {}
+                        _ => {
+                            tracing::error!(?def, "Encountered enclosing definition with no name");
+                        }
+                    }
+                }
             }
-
-            MonikerDescriptor { name: local.name(db).display(db, edition).to_string(), desc }
         }
-        Definition::Macro(m) => {
-            MonikerDescriptor { name: m.name(db).display(db, edition).to_string(), desc }
-        }
-        Definition::Function(f) => {
-            MonikerDescriptor { name: f.name(db).display(db, edition).to_string(), desc }
-        }
-        Definition::Variant(v) => {
-            MonikerDescriptor { name: v.name(db).display(db, edition).to_string(), desc }
-        }
-        Definition::Const(c) => {
-            MonikerDescriptor { name: c.name(db)?.display(db, edition).to_string(), desc }
-        }
-        Definition::Trait(trait_) => {
-            MonikerDescriptor { name: trait_.name(db).display(db, edition).to_string(), desc }
-        }
-        Definition::TraitAlias(ta) => {
-            MonikerDescriptor { name: ta.name(db).display(db, edition).to_string(), desc }
-        }
-        Definition::TypeAlias(ta) => {
-            MonikerDescriptor { name: ta.name(db).display(db, edition).to_string(), desc }
-        }
-        Definition::Module(m) => {
-            MonikerDescriptor { name: m.name(db)?.display(db, edition).to_string(), desc }
-        }
-        Definition::BuiltinType(b) => {
-            MonikerDescriptor { name: b.name().display(db, edition).to_string(), desc }
-        }
-        Definition::SelfType(imp) => MonikerDescriptor {
-            name: imp.self_ty(db).as_adt()?.name(db).display(db, edition).to_string(),
-            desc,
-        },
-        Definition::Field(it) => {
-            MonikerDescriptor { name: it.name(db).display(db, edition).to_string(), desc }
-        }
-        Definition::TupleField(it) => {
-            MonikerDescriptor { name: it.name().display(db, edition).to_string(), desc }
-        }
-        Definition::Adt(adt) => {
-            MonikerDescriptor { name: adt.name(db).display(db, edition).to_string(), desc }
-        }
-        Definition::Static(s) => {
-            MonikerDescriptor { name: s.name(db).display(db, edition).to_string(), desc }
-        }
-        Definition::ExternCrateDecl(m) => {
-            MonikerDescriptor { name: m.name(db).display(db, edition).to_string(), desc }
-        }
-    };
-
-    description.push(name_desc);
+        let Some(next_def) = def.enclosing_definition(db) else {
+            break;
+        };
+        def = next_def;
+    }
+    reverse_description.reverse();
+    let description = reverse_description;
 
-    Some(MonikerResult {
+    Some(Moniker {
         identifier: MonikerIdentifier {
             crate_name: krate.display_name(db)?.crate_name().to_string(),
             description,
@@ -417,17 +378,57 @@ pub(crate) fn def_to_moniker(
     })
 }
 
+fn display<T: HirDisplay>(
+    db: &RootDatabase,
+    edition: Edition,
+    module: hir::Module,
+    it: T,
+) -> String {
+    match it.display_source_code(db, module.into(), true) {
+        Ok(result) => result,
+        // Fallback on display variant that always succeeds
+        Err(_) => {
+            let fallback_result = it.display(db, edition).to_string();
+            tracing::error!(
+                display = %fallback_result, "`display_source_code` failed; falling back to using display"
+            );
+            fallback_result
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests {
-    use crate::fixture;
+    use crate::{fixture, MonikerResult};
 
     use super::MonikerKind;
 
+    #[allow(dead_code)]
     #[track_caller]
     fn no_moniker(ra_fixture: &str) {
         let (analysis, position) = fixture::position(ra_fixture);
         if let Some(x) = analysis.moniker(position).unwrap() {
-            assert_eq!(x.info.len(), 0, "Moniker founded but no moniker expected: {x:?}");
+            assert_eq!(x.info.len(), 0, "Moniker found but no moniker expected: {x:?}");
+        }
+    }
+
+    #[track_caller]
+    fn check_local_moniker(ra_fixture: &str, identifier: &str, package: &str, kind: MonikerKind) {
+        let (analysis, position) = fixture::position(ra_fixture);
+        let x = analysis.moniker(position).unwrap().expect("no moniker found").info;
+        assert_eq!(x.len(), 1);
+        match x.into_iter().next().unwrap() {
+            MonikerResult::Local { enclosing_moniker: Some(x) } => {
+                assert_eq!(identifier, x.identifier.to_string());
+                assert_eq!(package, format!("{:?}", x.package_information));
+                assert_eq!(kind, x.kind);
+            }
+            MonikerResult::Local { enclosing_moniker: None } => {
+                panic!("Unexpected local with no enclosing moniker");
+            }
+            MonikerResult::Moniker(_) => {
+                panic!("Unexpected non-local moniker");
+            }
         }
     }
 
@@ -436,10 +437,16 @@ mod tests {
         let (analysis, position) = fixture::position(ra_fixture);
         let x = analysis.moniker(position).unwrap().expect("no moniker found").info;
         assert_eq!(x.len(), 1);
-        let x = x.into_iter().next().unwrap();
-        assert_eq!(identifier, x.identifier.to_string());
-        assert_eq!(package, format!("{:?}", x.package_information));
-        assert_eq!(kind, x.kind);
+        match x.into_iter().next().unwrap() {
+            MonikerResult::Local { enclosing_moniker } => {
+                panic!("Unexpected local enclosed in {:?}", enclosing_moniker);
+            }
+            MonikerResult::Moniker(x) => {
+                assert_eq!(identifier, x.identifier.to_string());
+                assert_eq!(package, format!("{:?}", x.package_information));
+                assert_eq!(kind, x.kind);
+            }
+        }
     }
 
     #[test]
@@ -538,15 +545,13 @@ pub mod module {
     pub trait MyTrait {
         pub fn func() {}
     }
-
     struct MyStruct {}
-
     impl MyTrait for MyStruct {
         pub fn func$0() {}
     }
 }
 "#,
-            "foo::module::MyStruct::MyTrait::func",
+            "foo::module::impl::MyStruct::MyTrait::func",
             r#"PackageInformation { name: "foo", repo: Some("https://a.b/foo.git"), version: Some("0.1.0") }"#,
             MonikerKind::Export,
         );
@@ -573,8 +578,8 @@ pub struct St {
     }
 
     #[test]
-    fn no_moniker_for_local() {
-        no_moniker(
+    fn local() {
+        check_local_moniker(
             r#"
 //- /lib.rs crate:main deps:foo
 use foo::module::func;
@@ -588,6 +593,9 @@ pub mod module {
     }
 }
 "#,
+            "foo::module::func",
+            r#"PackageInformation { name: "foo", repo: Some("https://a.b/foo.git"), version: Some("0.1.0") }"#,
+            MonikerKind::Export,
         );
     }
 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/parent_module.rs b/src/tools/rust-analyzer/crates/ide/src/parent_module.rs
index 74c50fcac35..b51a5cc4f4c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/parent_module.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/parent_module.rs
@@ -34,7 +34,7 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<Na
     if let Some(m) = &module {
         if !m
             .item_list()
-            .map_or(false, |it| it.syntax().text_range().contains_inclusive(position.offset))
+            .is_some_and(|it| it.syntax().text_range().contains_inclusive(position.offset))
         {
             cov_mark::hit!(test_resolve_parent_module_on_module_decl);
             module = m.syntax().ancestors().skip(1).find_map(ast::Module::cast);
diff --git a/src/tools/rust-analyzer/crates/ide/src/references.rs b/src/tools/rust-analyzer/crates/ide/src/references.rs
index 339315db571..46714df8d69 100644
--- a/src/tools/rust-analyzer/crates/ide/src/references.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/references.rs
@@ -112,7 +112,7 @@ pub(crate) fn find_all_refs(
         Some(name) => {
             let def = match NameClass::classify(sema, &name)? {
                 NameClass::Definition(it) | NameClass::ConstReference(it) => it,
-                NameClass::PatFieldShorthand { local_def: _, field_ref } => {
+                NameClass::PatFieldShorthand { local_def: _, field_ref, adt_subst: _ } => {
                     Definition::Field(field_ref)
                 }
             };
@@ -156,10 +156,12 @@ pub(crate) fn find_defs<'a>(
                 let def = match name_like {
                     ast::NameLike::NameRef(name_ref) => {
                         match NameRefClass::classify(sema, &name_ref)? {
-                            NameRefClass::Definition(def) => def,
-                            NameRefClass::FieldShorthand { local_ref, field_ref: _ } => {
-                                Definition::Local(local_ref)
-                            }
+                            NameRefClass::Definition(def, _) => def,
+                            NameRefClass::FieldShorthand {
+                                local_ref,
+                                field_ref: _,
+                                adt_subst: _,
+                            } => Definition::Local(local_ref),
                             NameRefClass::ExternCrateShorthand { decl, .. } => {
                                 Definition::ExternCrateDecl(decl)
                             }
@@ -167,14 +169,14 @@ pub(crate) fn find_defs<'a>(
                     }
                     ast::NameLike::Name(name) => match NameClass::classify(sema, &name)? {
                         NameClass::Definition(it) | NameClass::ConstReference(it) => it,
-                        NameClass::PatFieldShorthand { local_def, field_ref: _ } => {
+                        NameClass::PatFieldShorthand { local_def, field_ref: _, adt_subst: _ } => {
                             Definition::Local(local_def)
                         }
                     },
                     ast::NameLike::Lifetime(lifetime) => {
                         NameRefClass::classify_lifetime(sema, &lifetime)
                             .and_then(|class| match class {
-                                NameRefClass::Definition(it) => Some(it),
+                                NameRefClass::Definition(it, _) => Some(it),
                                 _ => None,
                             })
                             .or_else(|| {
@@ -203,14 +205,14 @@ fn retain_adt_literal_usages(
                     reference
                         .name
                         .as_name_ref()
-                        .map_or(false, |name_ref| is_enum_lit_name_ref(sema, enum_, name_ref))
+                        .is_some_and(|name_ref| is_enum_lit_name_ref(sema, enum_, name_ref))
                 })
             });
             usages.references.retain(|_, it| !it.is_empty());
         }
         Definition::Adt(_) | Definition::Variant(_) => {
             refs.for_each(|it| {
-                it.retain(|reference| reference.name.as_name_ref().map_or(false, is_lit_name_ref))
+                it.retain(|reference| reference.name.as_name_ref().is_some_and(is_lit_name_ref))
             });
             usages.references.retain(|_, it| !it.is_empty());
         }
diff --git a/src/tools/rust-analyzer/crates/ide/src/rename.rs b/src/tools/rust-analyzer/crates/ide/src/rename.rs
index a9519c03b32..11bbd99110b 100644
--- a/src/tools/rust-analyzer/crates/ide/src/rename.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/rename.rs
@@ -227,8 +227,7 @@ fn find_definitions(
                 ast::NameLike::Name(name)
                     if name
                         .syntax()
-                        .parent()
-                        .map_or(false, |it| ast::Rename::can_cast(it.kind()))
+                        .parent().is_some_and(|it| ast::Rename::can_cast(it.kind()))
                         // FIXME: uncomment this once we resolve to usages to extern crate declarations
                         // && name
                         //     .syntax()
@@ -242,7 +241,7 @@ fn find_definitions(
                 ast::NameLike::Name(name) => NameClass::classify(sema, name)
                     .map(|class| match class {
                         NameClass::Definition(it) | NameClass::ConstReference(it) => it,
-                        NameClass::PatFieldShorthand { local_def, field_ref: _ } => {
+                        NameClass::PatFieldShorthand { local_def, field_ref: _, adt_subst: _ } => {
                             Definition::Local(local_def)
                         }
                     })
@@ -250,8 +249,8 @@ fn find_definitions(
                 ast::NameLike::NameRef(name_ref) => {
                     NameRefClass::classify(sema, name_ref)
                         .map(|class| match class {
-                            NameRefClass::Definition(def) => def,
-                            NameRefClass::FieldShorthand { local_ref, field_ref: _ } => {
+                            NameRefClass::Definition(def, _) => def,
+                            NameRefClass::FieldShorthand { local_ref, field_ref: _, adt_subst: _ } => {
                                 Definition::Local(local_ref)
                             }
                             NameRefClass::ExternCrateShorthand { decl, .. } => {
@@ -264,8 +263,7 @@ fn find_definitions(
                         .and_then(|def| {
                             // if the name differs from the definitions name it has to be an alias
                             if def
-                                .name(sema.db)
-                                .map_or(false, |it| !it.eq_ident(name_ref.text().as_str()))
+                                .name(sema.db).is_some_and(|it| !it.eq_ident(name_ref.text().as_str()))
                             {
                                 Err(format_err!("Renaming aliases is currently unsupported"))
                             } else {
@@ -276,7 +274,7 @@ fn find_definitions(
                 ast::NameLike::Lifetime(lifetime) => {
                     NameRefClass::classify_lifetime(sema, lifetime)
                         .and_then(|class| match class {
-                            NameRefClass::Definition(def) => Some(def),
+                            NameRefClass::Definition(def, _) => Some(def),
                             _ => None,
                         })
                         .or_else(|| {
diff --git a/src/tools/rust-analyzer/crates/ide/src/runnables.rs b/src/tools/rust-analyzer/crates/ide/src/runnables.rs
index d385e453e21..3e39c750b13 100644
--- a/src/tools/rust-analyzer/crates/ide/src/runnables.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/runnables.rs
@@ -1,10 +1,11 @@
-use std::fmt;
+use std::{fmt, sync::OnceLock};
 
+use arrayvec::ArrayVec;
 use ast::HasName;
 use cfg::{CfgAtom, CfgExpr};
 use hir::{
     db::HirDatabase, sym, AsAssocItem, AttrsWithOwner, HasAttrs, HasCrate, HasSource, HirFileIdExt,
-    Semantics,
+    ModPath, Name, PathKind, Semantics, Symbol,
 };
 use ide_assists::utils::{has_test_related_attribute, test_related_attribute_syn};
 use ide_db::{
@@ -15,11 +16,12 @@ use ide_db::{
     FilePosition, FxHashMap, FxHashSet, RootDatabase, SymbolKind,
 };
 use itertools::Itertools;
+use smallvec::SmallVec;
 use span::{Edition, TextSize};
 use stdx::format_to;
 use syntax::{
     ast::{self, AstNode},
-    SmolStr, SyntaxNode, ToSmolStr,
+    format_smolstr, SmolStr, SyntaxNode, ToSmolStr,
 };
 
 use crate::{references, FileId, NavigationTarget, ToNav, TryToNav};
@@ -30,6 +32,7 @@ pub struct Runnable {
     pub nav: NavigationTarget,
     pub kind: RunnableKind,
     pub cfg: Option<CfgExpr>,
+    pub update_test: UpdateTest,
 }
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
@@ -334,14 +337,20 @@ pub(crate) fn runnable_fn(
         }
     };
 
+    let fn_source = sema.source(def)?;
     let nav = NavigationTarget::from_named(
         sema.db,
-        def.source(sema.db)?.as_ref().map(|it| it as &dyn ast::HasName),
+        fn_source.as_ref().map(|it| it as &dyn ast::HasName),
         SymbolKind::Function,
     )
     .call_site();
+
+    let file_range = fn_source.syntax().original_file_range_with_macro_call_body(sema.db);
+    let update_test =
+        UpdateTest::find_snapshot_macro(sema, &fn_source.file_syntax(sema.db), file_range);
+
     let cfg = def.attrs(sema.db).cfg();
-    Some(Runnable { use_name_in_title: false, nav, kind, cfg })
+    Some(Runnable { use_name_in_title: false, nav, kind, cfg, update_test })
 }
 
 pub(crate) fn runnable_mod(
@@ -366,7 +375,22 @@ pub(crate) fn runnable_mod(
     let attrs = def.attrs(sema.db);
     let cfg = attrs.cfg();
     let nav = NavigationTarget::from_module_to_decl(sema.db, def).call_site();
-    Some(Runnable { use_name_in_title: false, nav, kind: RunnableKind::TestMod { path }, cfg })
+
+    let module_source = sema.module_definition_node(def);
+    let module_syntax = module_source.file_syntax(sema.db);
+    let file_range = hir::FileRange {
+        file_id: module_source.file_id.original_file(sema.db),
+        range: module_syntax.text_range(),
+    };
+    let update_test = UpdateTest::find_snapshot_macro(sema, &module_syntax, file_range);
+
+    Some(Runnable {
+        use_name_in_title: false,
+        nav,
+        kind: RunnableKind::TestMod { path },
+        cfg,
+        update_test,
+    })
 }
 
 pub(crate) fn runnable_impl(
@@ -392,7 +416,19 @@ pub(crate) fn runnable_impl(
     test_id.retain(|c| c != ' ');
     let test_id = TestId::Path(test_id);
 
-    Some(Runnable { use_name_in_title: false, nav, kind: RunnableKind::DocTest { test_id }, cfg })
+    let impl_source = sema.source(*def)?;
+    let impl_syntax = impl_source.syntax();
+    let file_range = impl_syntax.original_file_range_with_macro_call_body(sema.db);
+    let update_test =
+        UpdateTest::find_snapshot_macro(sema, &impl_syntax.file_syntax(sema.db), file_range);
+
+    Some(Runnable {
+        use_name_in_title: false,
+        nav,
+        kind: RunnableKind::DocTest { test_id },
+        cfg,
+        update_test,
+    })
 }
 
 fn has_cfg_test(attrs: AttrsWithOwner) -> bool {
@@ -404,6 +440,8 @@ fn runnable_mod_outline_definition(
     sema: &Semantics<'_, RootDatabase>,
     def: hir::Module,
 ) -> Option<Runnable> {
+    def.as_source_file_id(sema.db)?;
+
     if !has_test_function_or_multiple_test_submodules(sema, &def, has_cfg_test(def.attrs(sema.db)))
     {
         return None;
@@ -421,16 +459,22 @@ fn runnable_mod_outline_definition(
 
     let attrs = def.attrs(sema.db);
     let cfg = attrs.cfg();
-    if def.as_source_file_id(sema.db).is_some() {
-        Some(Runnable {
-            use_name_in_title: false,
-            nav: def.to_nav(sema.db).call_site(),
-            kind: RunnableKind::TestMod { path },
-            cfg,
-        })
-    } else {
-        None
-    }
+
+    let mod_source = sema.module_definition_node(def);
+    let mod_syntax = mod_source.file_syntax(sema.db);
+    let file_range = hir::FileRange {
+        file_id: mod_source.file_id.original_file(sema.db),
+        range: mod_syntax.text_range(),
+    };
+    let update_test = UpdateTest::find_snapshot_macro(sema, &mod_syntax, file_range);
+
+    Some(Runnable {
+        use_name_in_title: false,
+        nav: def.to_nav(sema.db).call_site(),
+        kind: RunnableKind::TestMod { path },
+        cfg,
+        update_test,
+    })
 }
 
 fn module_def_doctest(db: &RootDatabase, def: Definition) -> Option<Runnable> {
@@ -495,6 +539,7 @@ fn module_def_doctest(db: &RootDatabase, def: Definition) -> Option<Runnable> {
         nav,
         kind: RunnableKind::DocTest { test_id },
         cfg: attrs.cfg(),
+        update_test: UpdateTest::default(),
     };
     Some(res)
 }
@@ -515,7 +560,7 @@ fn has_runnable_doc_test(attrs: &hir::Attrs) -> bool {
     const RUSTDOC_CODE_BLOCK_ATTRIBUTES_RUNNABLE: &[&str] =
         &["", "rust", "should_panic", "edition2015", "edition2018", "edition2021"];
 
-    docs_from_attrs(attrs).map_or(false, |doc| {
+    docs_from_attrs(attrs).is_some_and(|doc| {
         let mut in_code_block = false;
 
         for line in doc.lines() {
@@ -575,6 +620,128 @@ fn has_test_function_or_multiple_test_submodules(
     number_of_test_submodules > 1
 }
 
+#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct UpdateTest {
+    pub expect_test: bool,
+    pub insta: bool,
+    pub snapbox: bool,
+}
+
+static SNAPSHOT_TEST_MACROS: OnceLock<FxHashMap<&str, Vec<ModPath>>> = OnceLock::new();
+
+impl UpdateTest {
+    const EXPECT_CRATE: &str = "expect_test";
+    const EXPECT_MACROS: &[&str] = &["expect", "expect_file"];
+
+    const INSTA_CRATE: &str = "insta";
+    const INSTA_MACROS: &[&str] = &[
+        "assert_snapshot",
+        "assert_debug_snapshot",
+        "assert_display_snapshot",
+        "assert_json_snapshot",
+        "assert_yaml_snapshot",
+        "assert_ron_snapshot",
+        "assert_toml_snapshot",
+        "assert_csv_snapshot",
+        "assert_compact_json_snapshot",
+        "assert_compact_debug_snapshot",
+        "assert_binary_snapshot",
+    ];
+
+    const SNAPBOX_CRATE: &str = "snapbox";
+    const SNAPBOX_MACROS: &[&str] = &["assert_data_eq", "file", "str"];
+
+    fn find_snapshot_macro(
+        sema: &Semantics<'_, RootDatabase>,
+        scope: &SyntaxNode,
+        file_range: hir::FileRange,
+    ) -> Self {
+        fn init<'a>(
+            krate_name: &'a str,
+            paths: &[&str],
+            map: &mut FxHashMap<&'a str, Vec<ModPath>>,
+        ) {
+            let mut res = Vec::with_capacity(paths.len());
+            let krate = Name::new_symbol_root(Symbol::intern(krate_name));
+            for path in paths {
+                let segments = [krate.clone(), Name::new_symbol_root(Symbol::intern(path))];
+                let mod_path = ModPath::from_segments(PathKind::Abs, segments);
+                res.push(mod_path);
+            }
+            map.insert(krate_name, res);
+        }
+
+        let mod_paths = SNAPSHOT_TEST_MACROS.get_or_init(|| {
+            let mut map = FxHashMap::default();
+            init(Self::EXPECT_CRATE, Self::EXPECT_MACROS, &mut map);
+            init(Self::INSTA_CRATE, Self::INSTA_MACROS, &mut map);
+            init(Self::SNAPBOX_CRATE, Self::SNAPBOX_MACROS, &mut map);
+            map
+        });
+
+        let search_scope = SearchScope::file_range(file_range);
+        let find_macro = |paths: &[ModPath]| {
+            for path in paths {
+                let Some(items) = sema.resolve_mod_path(scope, path) else {
+                    continue;
+                };
+                for item in items {
+                    if let hir::ItemInNs::Macros(makro) = item {
+                        if Definition::Macro(makro)
+                            .usages(sema)
+                            .in_scope(&search_scope)
+                            .at_least_one()
+                        {
+                            return true;
+                        }
+                    }
+                }
+            }
+            false
+        };
+
+        UpdateTest {
+            expect_test: find_macro(mod_paths.get(Self::EXPECT_CRATE).unwrap()),
+            insta: find_macro(mod_paths.get(Self::INSTA_CRATE).unwrap()),
+            snapbox: find_macro(mod_paths.get(Self::SNAPBOX_CRATE).unwrap()),
+        }
+    }
+
+    pub fn label(&self) -> Option<SmolStr> {
+        let mut builder: SmallVec<[_; 3]> = SmallVec::new();
+        if self.expect_test {
+            builder.push("Expect");
+        }
+        if self.insta {
+            builder.push("Insta");
+        }
+        if self.snapbox {
+            builder.push("Snapbox");
+        }
+
+        let res: SmolStr = builder.join(" + ").into();
+        if res.is_empty() {
+            None
+        } else {
+            Some(format_smolstr!("↺\u{fe0e} Update Tests ({res})"))
+        }
+    }
+
+    pub fn env(&self) -> ArrayVec<(&str, &str), 3> {
+        let mut env = ArrayVec::new();
+        if self.expect_test {
+            env.push(("UPDATE_EXPECT", "1"));
+        }
+        if self.insta {
+            env.push(("INSTA_UPDATE", "always"));
+        }
+        if self.snapbox {
+            env.push(("SNAPSHOTS", "overwrite"));
+        }
+        env
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use expect_test::{expect, Expect};
@@ -1337,18 +1504,18 @@ mod tests {
                         file_id: FileId(
                             0,
                         ),
-                        full_range: 52..115,
-                        focus_range: 67..75,
-                        name: "foo_test",
+                        full_range: 121..185,
+                        focus_range: 136..145,
+                        name: "foo2_test",
                         kind: Function,
                     },
                     NavigationTarget {
                         file_id: FileId(
                             0,
                         ),
-                        full_range: 121..185,
-                        focus_range: 136..145,
-                        name: "foo2_test",
+                        full_range: 52..115,
+                        focus_range: 67..75,
+                        name: "foo_test",
                         kind: Function,
                     },
                 ]
diff --git a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
index 516f64959ce..84ccadc8c4e 100644
--- a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
@@ -165,7 +165,7 @@ fn signature_help_for_call(
         if let Some(callable) = ast::CallableExpr::cast(nodes.next()?) {
             let inside_callable = callable
                 .arg_list()
-                .map_or(false, |it| it.syntax().text_range().contains(token.text_range().start()));
+                .is_some_and(|it| it.syntax().text_range().contains(token.text_range().start()));
             if inside_callable {
                 break callable;
             }
@@ -650,7 +650,7 @@ fn signature_help_for_tuple_pat_ish(
 ) -> SignatureHelp {
     let rest_pat = field_pats.find(|it| matches!(it, ast::Pat::RestPat(_)));
     let is_left_of_rest_pat =
-        rest_pat.map_or(true, |it| token.text_range().start() < it.syntax().text_range().end());
+        rest_pat.is_none_or(|it| token.text_range().start() < it.syntax().text_range().end());
 
     let commas = pat
         .children_with_tokens()
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 0f4b5e7d87a..700e166b238 100644
--- a/src/tools/rust-analyzer/crates/ide/src/static_index.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/static_index.rs
@@ -13,11 +13,10 @@ use ide_db::{
 use span::Edition;
 use syntax::{AstNode, SyntaxKind::*, SyntaxNode, TextRange, T};
 
-use crate::inlay_hints::InlayFieldsToResolve;
 use crate::navigation_target::UpmappingResult;
 use crate::{
-    hover::hover_for_definition,
-    inlay_hints::AdjustmentHintsMode,
+    hover::{hover_for_definition, SubstTyLen},
+    inlay_hints::{AdjustmentHintsMode, InlayFieldsToResolve},
     moniker::{def_to_kind, def_to_moniker, MonikerResult, SymbolInformationKind},
     parent_module::crates_for,
     Analysis, Fold, HoverConfig, HoverResult, InlayHint, InlayHintsConfig, TryToNav,
@@ -49,7 +48,6 @@ pub struct TokenStaticData {
     pub references: Vec<ReferenceData>,
     pub moniker: Option<MonikerResult>,
     pub display_name: Option<String>,
-    pub enclosing_moniker: Option<MonikerResult>,
     pub signature: Option<String>,
     pub kind: SymbolInformationKind,
 }
@@ -186,6 +184,7 @@ impl StaticIndex<'_> {
             max_trait_assoc_items_count: None,
             max_fields_count: Some(5),
             max_enum_variants_count: Some(5),
+            max_subst_ty_len: SubstTyLen::Unlimited,
         };
         let tokens = tokens.filter(|token| {
             matches!(
@@ -210,6 +209,7 @@ impl StaticIndex<'_> {
                         &sema,
                         file_id,
                         def,
+                        None,
                         &node,
                         None,
                         false,
@@ -224,9 +224,6 @@ impl StaticIndex<'_> {
                     display_name: def
                         .name(self.db)
                         .map(|name| name.display(self.db, edition).to_string()),
-                    enclosing_moniker: current_crate
-                        .zip(def.enclosing_definition(self.db))
-                        .and_then(|(cc, enclosing_def)| def_to_moniker(self.db, enclosing_def, cc)),
                     signature: Some(def.label(self.db, edition)),
                     kind: def_to_kind(self.db, def),
                 });
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
index 0747d1b404b..f53f0aec098 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
@@ -346,7 +346,7 @@ fn traverse(
                         macro_highlighter = MacroHighlighter::default();
                     }
                     Some(item)
-                        if attr_or_derive_item.as_ref().map_or(false, |it| *it.item() == item) =>
+                        if attr_or_derive_item.as_ref().is_some_and(|it| *it.item() == item) =>
                     {
                         attr_or_derive_item = None;
                     }
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 3767a3917ce..4f3d5d9d00c 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
@@ -76,7 +76,7 @@ pub(super) fn name_like(
             Some(IdentClass::NameClass(NameClass::Definition(def))) => {
                 highlight_def(sema, krate, def) | HlMod::Definition
             }
-            Some(IdentClass::NameRefClass(NameRefClass::Definition(def))) => {
+            Some(IdentClass::NameRefClass(NameRefClass::Definition(def, _))) => {
                 highlight_def(sema, krate, def)
             }
             // FIXME: Fallback for 'static and '_, as we do not resolve these yet
@@ -155,7 +155,7 @@ fn punctuation(
                 if parent
                     .as_ref()
                     .and_then(SyntaxNode::parent)
-                    .map_or(false, |it| it.kind() == MACRO_RULES) =>
+                    .is_some_and(|it| it.kind() == MACRO_RULES) =>
             {
                 return HlOperator::Other.into()
             }
@@ -193,7 +193,7 @@ fn keyword(
         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| {
+            if token.parent().is_some_and(|it| {
                 matches!(
                     it.kind(),
                     SyntaxKind::CONST
@@ -253,14 +253,14 @@ fn highlight_name_ref(
             && !sema
                 .hir_file_for(name_ref.syntax())
                 .macro_file()
-                .map_or(false, |it| it.is_derive_attr_pseudo_expansion(sema.db)) =>
+                .is_some_and(|it| it.is_derive_attr_pseudo_expansion(sema.db)) =>
         {
             return HlTag::Symbol(SymbolKind::Attribute).into();
         }
         None => return HlTag::UnresolvedReference.into(),
     };
     let mut h = match name_class {
-        NameRefClass::Definition(def) => {
+        NameRefClass::Definition(def, _) => {
             if let Definition::Local(local) = &def {
                 let name = local.name(db);
                 let shadow_count = bindings_shadow_count.entry(name.clone()).or_default();
@@ -275,7 +275,7 @@ fn highlight_name_ref(
                 }
                 Definition::Trait(trait_) if trait_.is_unsafe(db) => {
                     if ast::Impl::for_trait_name_ref(&name_ref)
-                        .map_or(false, |impl_| impl_.unsafe_token().is_some())
+                        .is_some_and(|impl_| impl_.unsafe_token().is_some())
                     {
                         h |= HlMod::Unsafe;
                     }
@@ -550,7 +550,7 @@ pub(super) fn highlight_def(
 
     let def_crate = def.krate(db);
     let is_from_other_crate = def_crate != Some(krate);
-    let is_from_builtin_crate = def_crate.map_or(false, |def_crate| def_crate.is_builtin(db));
+    let is_from_builtin_crate = def_crate.is_some_and(|def_crate| def_crate.is_builtin(db));
     let is_builtin = matches!(
         def,
         Definition::BuiltinType(_) | Definition::BuiltinLifetime(_) | Definition::BuiltinAttr(_)
@@ -688,7 +688,7 @@ fn highlight_name_ref_by_syntax(
             let h = HlTag::Symbol(SymbolKind::Field);
             let is_union = ast::FieldExpr::cast(parent)
                 .and_then(|field_expr| sema.resolve_field(&field_expr))
-                .map_or(false, |field| match field {
+                .is_some_and(|field| match field {
                     Either::Left(field) => {
                         matches!(field.parent_def(sema.db), hir::VariantDef::Union(_))
                     }
@@ -764,5 +764,5 @@ fn parents_match(mut node: NodeOrToken<SyntaxNode, SyntaxToken>, mut kinds: &[Sy
 }
 
 fn parent_matches<N: AstNode>(token: &SyntaxToken) -> bool {
-    token.parent().map_or(false, |it| N::can_cast(it.kind()))
+    token.parent().is_some_and(|it| N::can_cast(it.kind()))
 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs
index 5583f1bc8df..0a157c157c3 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs
@@ -28,7 +28,7 @@ pub(super) fn ra_fixture(
     expanded: &ast::String,
 ) -> Option<()> {
     let active_parameter = ActiveParameter::at_token(sema, expanded.syntax().clone())?;
-    if !active_parameter.ident().map_or(false, |name| name.text().starts_with("ra_fixture")) {
+    if !active_parameter.ident().is_some_and(|name| name.text().starts_with("ra_fixture")) {
         return None;
     }
     let value = literal.value().ok()?;
@@ -279,9 +279,7 @@ fn find_doc_string_in_attr(attr: &hir::Attr, it: &ast::Attr) -> Option<ast::Stri
                 .descendants_with_tokens()
                 .filter_map(NodeOrToken::into_token)
                 .filter_map(ast::String::cast)
-                .find(|string| {
-                    string.text().get(1..string.text().len() - 1).map_or(false, |it| it == text)
-                })
+                .find(|string| string.text().get(1..string.text().len() - 1) == Some(text))
         }
         _ => None,
     }
diff --git a/src/tools/rust-analyzer/crates/ide/src/typing.rs b/src/tools/rust-analyzer/crates/ide/src/typing.rs
index d37318ff457..8998934e0e8 100644
--- a/src/tools/rust-analyzer/crates/ide/src/typing.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/typing.rs
@@ -174,7 +174,7 @@ fn on_delimited_node_typed(
     kinds: &[fn(SyntaxKind) -> bool],
 ) -> Option<TextEdit> {
     let t = reparsed.syntax().token_at_offset(offset).right_biased()?;
-    if t.prev_token().map_or(false, |t| t.kind().is_any_identifier()) {
+    if t.prev_token().is_some_and(|t| t.kind().is_any_identifier()) {
         return None;
     }
     let (filter, node) = t
diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
index c15751e7c68..66b8900109c 100644
--- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
+++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
@@ -361,6 +361,7 @@ define_symbols! {
     partial_ord,
     PartialEq,
     PartialOrd,
+    CoercePointee,
     path,
     Pending,
     phantom_data,
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 1b2162dad0f..73899408652 100644
--- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
@@ -14,7 +14,7 @@ use ide_db::{
     prime_caches, ChangeWithProcMacros, FxHashMap, RootDatabase,
 };
 use itertools::Itertools;
-use proc_macro_api::{MacroDylib, ProcMacroServer};
+use proc_macro_api::{MacroDylib, ProcMacroClient};
 use project_model::{CargoConfig, PackageRoot, ProjectManifest, ProjectWorkspace};
 use span::Span;
 use vfs::{
@@ -42,7 +42,7 @@ pub fn load_workspace_at(
     cargo_config: &CargoConfig,
     load_config: &LoadCargoConfig,
     progress: &dyn Fn(String),
-) -> anyhow::Result<(RootDatabase, vfs::Vfs, Option<ProcMacroServer>)> {
+) -> anyhow::Result<(RootDatabase, vfs::Vfs, Option<ProcMacroClient>)> {
     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)?;
@@ -59,7 +59,7 @@ pub fn load_workspace(
     ws: ProjectWorkspace,
     extra_env: &FxHashMap<String, String>,
     load_config: &LoadCargoConfig,
-) -> anyhow::Result<(RootDatabase, vfs::Vfs, Option<ProcMacroServer>)> {
+) -> anyhow::Result<(RootDatabase, vfs::Vfs, Option<ProcMacroClient>)> {
     let (sender, receiver) = unbounded();
     let mut vfs = vfs::Vfs::default();
     let mut loader = {
@@ -71,10 +71,10 @@ pub fn load_workspace(
     let proc_macro_server = match &load_config.with_proc_macro_server {
         ProcMacroServerChoice::Sysroot => ws
             .find_sysroot_proc_macro_srv()
-            .and_then(|it| ProcMacroServer::spawn(&it, extra_env).map_err(Into::into))
+            .and_then(|it| ProcMacroClient::spawn(&it, extra_env).map_err(Into::into))
             .map_err(|e| (e, true)),
         ProcMacroServerChoice::Explicit(path) => {
-            ProcMacroServer::spawn(path, extra_env).map_err(Into::into).map_err(|e| (e, true))
+            ProcMacroClient::spawn(path, extra_env).map_err(Into::into).map_err(|e| (e, true))
         }
         ProcMacroServerChoice::None => {
             Err((anyhow::format_err!("proc macro server disabled"), false))
@@ -82,7 +82,7 @@ pub fn load_workspace(
     };
     match &proc_macro_server {
         Ok(server) => {
-            tracing::info!(path=%server.path(), "Proc-macro server started")
+            tracing::info!(path=%server.server_path(), "Proc-macro server started")
         }
         Err((e, _)) => {
             tracing::info!(%e, "Failed to start proc-macro server")
@@ -362,7 +362,7 @@ impl SourceRootConfig {
 
 /// Load the proc-macros for the given lib path, disabling all expanders whose names are in `ignored_macros`.
 pub fn load_proc_macro(
-    server: &ProcMacroServer,
+    server: &ProcMacroClient,
     path: &AbsPath,
     ignored_macros: &[Box<str>],
 ) -> ProcMacroLoadResult {
@@ -476,17 +476,17 @@ struct Expander(proc_macro_api::ProcMacro);
 impl ProcMacroExpander for Expander {
     fn expand(
         &self,
-        subtree: &tt::Subtree<Span>,
-        attrs: Option<&tt::Subtree<Span>>,
+        subtree: &tt::TopSubtree<Span>,
+        attrs: Option<&tt::TopSubtree<Span>>,
         env: &Env,
         def_site: Span,
         call_site: Span,
         mixed_site: Span,
         current_dir: Option<String>,
-    ) -> Result<tt::Subtree<Span>, ProcMacroExpansionError> {
+    ) -> Result<tt::TopSubtree<Span>, ProcMacroExpansionError> {
         match self.0.expand(
-            subtree,
-            attrs,
+            subtree.view(),
+            attrs.map(|attrs| attrs.view()),
             env.clone().into(),
             def_site,
             call_site,
diff --git a/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs b/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs
index 270bc05a4ee..89c30030037 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/benchmark.rs
@@ -53,11 +53,11 @@ fn benchmark_expand_macro_rules() {
             .map(|(id, tt)| {
                 let res = rules[&id].expand(&tt, |_| (), DUMMY, Edition::CURRENT);
                 assert!(res.err.is_none());
-                res.value.0.token_trees.len()
+                res.value.0 .0.len()
             })
             .sum()
     };
-    assert_eq!(hash, 65720);
+    assert_eq!(hash, 450144);
 }
 
 fn macro_rules_fixtures() -> FxHashMap<String, DeclarativeMacro> {
@@ -68,7 +68,7 @@ fn macro_rules_fixtures() -> FxHashMap<String, DeclarativeMacro> {
         .collect()
 }
 
-fn macro_rules_fixtures_tt() -> FxHashMap<String, tt::Subtree<Span>> {
+fn macro_rules_fixtures_tt() -> FxHashMap<String, tt::TopSubtree<Span>> {
     let fixture = bench_fixture::numerous_macro_rules();
     let source_file = ast::SourceFile::parse(&fixture, span::Edition::CURRENT).ok().unwrap();
 
@@ -92,7 +92,7 @@ fn macro_rules_fixtures_tt() -> FxHashMap<String, tt::Subtree<Span>> {
 /// Generate random invocation fixtures from rules
 fn invocation_fixtures(
     rules: &FxHashMap<String, DeclarativeMacro>,
-) -> Vec<(String, tt::Subtree<Span>)> {
+) -> Vec<(String, tt::TopSubtree<Span>)> {
     let mut seed = 123456789;
     let mut res = Vec::new();
 
@@ -112,19 +112,16 @@ fn invocation_fixtures(
                 // So we just skip any error cases and try again
                 let mut try_cnt = 0;
                 loop {
-                    let mut token_trees = Vec::new();
+                    let mut builder = tt::TopSubtreeBuilder::new(tt::Delimiter {
+                        open: DUMMY,
+                        close: DUMMY,
+                        kind: tt::DelimiterKind::Invisible,
+                    });
                     for op in rule.lhs.iter() {
-                        collect_from_op(op, &mut token_trees, &mut seed);
+                        collect_from_op(op, &mut builder, &mut seed);
                     }
+                    let subtree = builder.build();
 
-                    let subtree = tt::Subtree {
-                        delimiter: tt::Delimiter {
-                            open: DUMMY,
-                            close: DUMMY,
-                            kind: tt::DelimiterKind::Invisible,
-                        },
-                        token_trees: token_trees.into_boxed_slice(),
-                    };
                     if it.expand(&subtree, |_| (), DUMMY, Edition::CURRENT).err.is_none() {
                         res.push((name.clone(), subtree));
                         break;
@@ -139,43 +136,41 @@ fn invocation_fixtures(
     }
     return res;
 
-    fn collect_from_op(op: &Op, token_trees: &mut Vec<tt::TokenTree<Span>>, seed: &mut usize) {
+    fn collect_from_op(op: &Op, builder: &mut tt::TopSubtreeBuilder<Span>, seed: &mut usize) {
         return match op {
             Op::Var { kind, .. } => match kind.as_ref() {
-                Some(MetaVarKind::Ident) => token_trees.push(make_ident("foo")),
-                Some(MetaVarKind::Ty) => token_trees.push(make_ident("Foo")),
-                Some(MetaVarKind::Tt) => token_trees.push(make_ident("foo")),
-                Some(MetaVarKind::Vis) => token_trees.push(make_ident("pub")),
-                Some(MetaVarKind::Pat) => token_trees.push(make_ident("foo")),
-                Some(MetaVarKind::Path) => token_trees.push(make_ident("foo")),
-                Some(MetaVarKind::Literal) => token_trees.push(make_literal("1")),
-                Some(MetaVarKind::Expr(_)) => token_trees.push(make_ident("foo")),
+                Some(MetaVarKind::Ident) => builder.push(make_ident("foo")),
+                Some(MetaVarKind::Ty) => builder.push(make_ident("Foo")),
+                Some(MetaVarKind::Tt) => builder.push(make_ident("foo")),
+                Some(MetaVarKind::Vis) => builder.push(make_ident("pub")),
+                Some(MetaVarKind::Pat) => builder.push(make_ident("foo")),
+                Some(MetaVarKind::Path) => builder.push(make_ident("foo")),
+                Some(MetaVarKind::Literal) => builder.push(make_literal("1")),
+                Some(MetaVarKind::Expr(_)) => builder.push(make_ident("foo")),
                 Some(MetaVarKind::Lifetime) => {
-                    token_trees.push(make_punct('\''));
-                    token_trees.push(make_ident("a"));
-                }
-                Some(MetaVarKind::Block) => {
-                    token_trees.push(make_subtree(tt::DelimiterKind::Brace, None))
+                    builder.push(make_punct('\''));
+                    builder.push(make_ident("a"));
                 }
+                Some(MetaVarKind::Block) => make_subtree(tt::DelimiterKind::Brace, builder),
                 Some(MetaVarKind::Item) => {
-                    token_trees.push(make_ident("fn"));
-                    token_trees.push(make_ident("foo"));
-                    token_trees.push(make_subtree(tt::DelimiterKind::Parenthesis, None));
-                    token_trees.push(make_subtree(tt::DelimiterKind::Brace, None));
+                    builder.push(make_ident("fn"));
+                    builder.push(make_ident("foo"));
+                    make_subtree(tt::DelimiterKind::Parenthesis, builder);
+                    make_subtree(tt::DelimiterKind::Brace, builder);
                 }
                 Some(MetaVarKind::Meta) => {
-                    token_trees.push(make_ident("foo"));
-                    token_trees.push(make_subtree(tt::DelimiterKind::Parenthesis, None));
+                    builder.push(make_ident("foo"));
+                    make_subtree(tt::DelimiterKind::Parenthesis, builder);
                 }
 
                 None => (),
                 Some(kind) => panic!("Unhandled kind {kind:?}"),
             },
-            Op::Literal(it) => token_trees.push(tt::Leaf::from(it.clone()).into()),
-            Op::Ident(it) => token_trees.push(tt::Leaf::from(it.clone()).into()),
+            Op::Literal(it) => builder.push(tt::Leaf::from(it.clone())),
+            Op::Ident(it) => builder.push(tt::Leaf::from(it.clone())),
             Op::Punct(puncts) => {
                 for punct in puncts.as_slice() {
-                    token_trees.push(tt::Leaf::from(*punct).into());
+                    builder.push(tt::Leaf::from(*punct));
                 }
             }
             Op::Repeat { tokens, kind, separator } => {
@@ -187,20 +182,18 @@ fn invocation_fixtures(
                 };
                 for i in 0..cnt {
                     for it in tokens.iter() {
-                        collect_from_op(it, token_trees, seed);
+                        collect_from_op(it, builder, seed);
                     }
                     if i + 1 != cnt {
                         if let Some(sep) = separator {
                             match &**sep {
                                 Separator::Literal(it) => {
-                                    token_trees.push(tt::Leaf::Literal(it.clone()).into())
-                                }
-                                Separator::Ident(it) => {
-                                    token_trees.push(tt::Leaf::Ident(it.clone()).into())
+                                    builder.push(tt::Leaf::Literal(it.clone()))
                                 }
+                                Separator::Ident(it) => builder.push(tt::Leaf::Ident(it.clone())),
                                 Separator::Puncts(puncts) => {
                                     for it in puncts {
-                                        token_trees.push(tt::Leaf::Punct(*it).into())
+                                        builder.push(tt::Leaf::Punct(*it))
                                     }
                                 }
                             };
@@ -209,15 +202,9 @@ fn invocation_fixtures(
                 }
             }
             Op::Subtree { tokens, delimiter } => {
-                let mut subtree = Vec::new();
-                tokens.iter().for_each(|it| {
-                    collect_from_op(it, &mut subtree, seed);
-                });
-
-                let subtree =
-                    tt::Subtree { delimiter: *delimiter, token_trees: subtree.into_boxed_slice() };
-
-                token_trees.push(subtree.into());
+                builder.open(delimiter.kind, delimiter.open);
+                tokens.iter().for_each(|it| collect_from_op(it, builder, seed));
+                builder.close(delimiter.close);
             }
             Op::Ignore { .. }
             | Op::Index { .. }
@@ -233,35 +220,27 @@ fn invocation_fixtures(
             *seed = usize::wrapping_add(usize::wrapping_mul(*seed, a), c);
             *seed
         }
-        fn make_ident(ident: &str) -> tt::TokenTree<Span> {
+        fn make_ident(ident: &str) -> tt::Leaf<Span> {
             tt::Leaf::Ident(tt::Ident {
                 span: DUMMY,
                 sym: Symbol::intern(ident),
                 is_raw: tt::IdentIsRaw::No,
             })
-            .into()
         }
-        fn make_punct(char: char) -> tt::TokenTree<Span> {
-            tt::Leaf::Punct(tt::Punct { span: DUMMY, char, spacing: tt::Spacing::Alone }).into()
+        fn make_punct(char: char) -> tt::Leaf<Span> {
+            tt::Leaf::Punct(tt::Punct { span: DUMMY, char, spacing: tt::Spacing::Alone })
         }
-        fn make_literal(lit: &str) -> tt::TokenTree<Span> {
+        fn make_literal(lit: &str) -> tt::Leaf<Span> {
             tt::Leaf::Literal(tt::Literal {
                 span: DUMMY,
                 symbol: Symbol::intern(lit),
                 kind: tt::LitKind::Str,
                 suffix: None,
             })
-            .into()
         }
-        fn make_subtree(
-            kind: tt::DelimiterKind,
-            token_trees: Option<Vec<tt::TokenTree<Span>>>,
-        ) -> tt::TokenTree<Span> {
-            tt::Subtree {
-                delimiter: tt::Delimiter { open: DUMMY, close: DUMMY, kind },
-                token_trees: token_trees.map(Vec::into_boxed_slice).unwrap_or_default(),
-            }
-            .into()
+        fn make_subtree(kind: tt::DelimiterKind, builder: &mut tt::TopSubtreeBuilder<Span>) {
+            builder.open(kind, DUMMY);
+            builder.close(DUMMY);
         }
     }
 }
diff --git a/src/tools/rust-analyzer/crates/mbe/src/expander.rs b/src/tools/rust-analyzer/crates/mbe/src/expander.rs
index 1979e5171ab..5539a88c707 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/expander.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/expander.rs
@@ -13,12 +13,12 @@ use crate::{parser::MetaVarKind, ExpandError, ExpandErrorKind, ExpandResult, Mat
 
 pub(crate) fn expand_rules(
     rules: &[crate::Rule],
-    input: &tt::Subtree<Span>,
+    input: &tt::TopSubtree<Span>,
     marker: impl Fn(&mut Span) + Copy,
     call_site: Span,
     def_site_edition: Edition,
-) -> ExpandResult<(tt::Subtree<Span>, MatchedArmIndex)> {
-    let mut match_: Option<(matcher::Match, &crate::Rule, usize)> = None;
+) -> ExpandResult<(tt::TopSubtree<Span>, MatchedArmIndex)> {
+    let mut match_: Option<(matcher::Match<'_>, &crate::Rule, usize)> = None;
     for (idx, rule) in rules.iter().enumerate() {
         let new_match = matcher::match_(&rule.lhs, input, def_site_edition);
 
@@ -50,13 +50,7 @@ pub(crate) fn expand_rules(
         ExpandResult { value: (value, idx.try_into().ok()), err: match_.err.or(transcribe_err) }
     } else {
         ExpandResult::new(
-            (
-                tt::Subtree {
-                    delimiter: tt::Delimiter::invisible_spanned(call_site),
-                    token_trees: Box::default(),
-                },
-                None,
-            ),
+            (tt::TopSubtree::empty(tt::DelimSpan::from_single(call_site)), None),
             ExpandError::new(call_site, ExpandErrorKind::NoMatchingRule),
         )
     }
@@ -107,32 +101,35 @@ pub(crate) fn expand_rules(
 /// In other words, `Bindings` is a *multi* mapping from `Symbol` to
 /// `tt::TokenTree`, where the index to select a particular `TokenTree` among
 /// many is not a plain `usize`, but a `&[usize]`.
-#[derive(Debug, Default, Clone, PartialEq, Eq)]
-struct Bindings {
-    inner: FxHashMap<Symbol, Binding>,
+#[derive(Debug, Default, Clone)]
+struct Bindings<'a> {
+    inner: FxHashMap<Symbol, Binding<'a>>,
 }
 
-#[derive(Debug, Clone, PartialEq, Eq)]
-enum Binding {
-    Fragment(Fragment),
-    Nested(Vec<Binding>),
+#[derive(Debug, Clone)]
+enum Binding<'a> {
+    Fragment(Fragment<'a>),
+    Nested(Vec<Binding<'a>>),
     Empty,
     Missing(MetaVarKind),
 }
 
-#[derive(Debug, Clone, PartialEq, Eq)]
-enum Fragment {
+#[derive(Debug, Default, Clone)]
+enum Fragment<'a> {
+    #[default]
     Empty,
     /// token fragments are just copy-pasted into the output
-    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.
+    Tokens(tt::TokenTreesView<'a, Span>),
+    /// Expr ast fragments are surrounded with `()` on transcription 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.
     ///
     /// 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<Span>),
+    ///
+    /// The span of the outer delimiters is marked on transcription.
+    Expr(tt::TokenTreesView<'a, 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.
@@ -142,5 +139,18 @@ enum Fragment {
     /// 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<Span>),
+    Path(tt::TokenTreesView<'a, Span>),
+    TokensOwned(tt::TopSubtree<Span>),
+}
+
+impl Fragment<'_> {
+    fn is_empty(&self) -> bool {
+        match self {
+            Fragment::Empty => true,
+            Fragment::Tokens(it) => it.len() == 0,
+            Fragment::Expr(it) => it.len() == 0,
+            Fragment::Path(it) => it.len() == 0,
+            Fragment::TokensOwned(it) => it.0.is_empty(),
+        }
+    }
 }
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 95641abc0f3..b7f25aa3809 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/expander/matcher.rs
@@ -64,7 +64,10 @@ use std::{rc::Rc, sync::Arc};
 use intern::{sym, Symbol};
 use smallvec::{smallvec, SmallVec};
 use span::{Edition, Span};
-use tt::{iter::TtIter, DelimSpan};
+use tt::{
+    iter::{TtElement, TtIter},
+    DelimSpan,
+};
 
 use crate::{
     expander::{Binding, Bindings, ExpandResult, Fragment},
@@ -73,7 +76,7 @@ use crate::{
     ExpandError, ExpandErrorKind, MetaTemplate, ValueResult,
 };
 
-impl Bindings {
+impl<'a> Bindings<'a> {
     fn push_optional(&mut self, name: Symbol) {
         self.inner.insert(name, Binding::Fragment(Fragment::Empty));
     }
@@ -82,14 +85,14 @@ impl Bindings {
         self.inner.insert(name, Binding::Empty);
     }
 
-    fn bindings(&self) -> impl Iterator<Item = &Binding> {
+    fn bindings(&self) -> impl Iterator<Item = &Binding<'a>> {
         self.inner.values()
     }
 }
 
-#[derive(Clone, Default, Debug, PartialEq, Eq)]
-pub(super) struct Match {
-    pub(super) bindings: Bindings,
+#[derive(Clone, Default, Debug)]
+pub(super) struct Match<'a> {
+    pub(super) bindings: Bindings<'a>,
     /// We currently just keep the first error and count the rest to compare matches.
     pub(super) err: Option<ExpandError>,
     pub(super) err_count: usize,
@@ -99,7 +102,7 @@ pub(super) struct Match {
     pub(super) bound_count: usize,
 }
 
-impl Match {
+impl Match<'_> {
     fn add_err(&mut self, err: ExpandError) {
         let prev_err = self.err.take();
         self.err = prev_err.or(Some(err));
@@ -108,12 +111,16 @@ impl Match {
 }
 
 /// Matching errors are added to the `Match`.
-pub(super) fn match_(pattern: &MetaTemplate, input: &tt::Subtree<Span>, edition: Edition) -> Match {
+pub(super) fn match_<'t>(
+    pattern: &'t MetaTemplate,
+    input: &'t tt::TopSubtree<Span>,
+    edition: Edition,
+) -> Match<'t> {
     let mut res = match_loop(pattern, input, edition);
     res.bound_count = count(res.bindings.bindings());
     return res;
 
-    fn count<'a>(bindings: impl Iterator<Item = &'a Binding>) -> usize {
+    fn count<'a>(bindings: impl Iterator<Item = &'a Binding<'a>>) -> usize {
         bindings
             .map(|it| match it {
                 Binding::Fragment(_) => 1,
@@ -126,10 +133,10 @@ pub(super) fn match_(pattern: &MetaTemplate, input: &tt::Subtree<Span>, edition:
 }
 
 #[derive(Debug, Clone)]
-enum BindingKind {
+enum BindingKind<'a> {
     Empty(Symbol),
     Optional(Symbol),
-    Fragment(Symbol, Fragment),
+    Fragment(Symbol, Fragment<'a>),
     Missing(Symbol, MetaVarKind),
     Nested(usize, usize),
 }
@@ -144,12 +151,12 @@ enum LinkNode<T> {
 }
 
 #[derive(Default)]
-struct BindingsBuilder {
-    nodes: Vec<Vec<LinkNode<Rc<BindingKind>>>>,
+struct BindingsBuilder<'a> {
+    nodes: Vec<Vec<LinkNode<Rc<BindingKind<'a>>>>>,
     nested: Vec<Vec<LinkNode<usize>>>,
 }
 
-impl BindingsBuilder {
+impl<'a> BindingsBuilder<'a> {
     fn alloc(&mut self) -> BindingsIdx {
         let idx = self.nodes.len();
         self.nodes.push(Vec::new());
@@ -186,7 +193,7 @@ impl BindingsBuilder {
         self.nodes[idx.0].push(LinkNode::Node(Rc::new(BindingKind::Optional(var.clone()))));
     }
 
-    fn push_fragment(&mut self, idx: &mut BindingsIdx, var: &Symbol, fragment: Fragment) {
+    fn push_fragment(&mut self, idx: &mut BindingsIdx, var: &Symbol, fragment: Fragment<'a>) {
         self.nodes[idx.0]
             .push(LinkNode::Node(Rc::new(BindingKind::Fragment(var.clone(), fragment))));
     }
@@ -207,11 +214,11 @@ impl BindingsBuilder {
         idx.0 = new_idx;
     }
 
-    fn build(self, idx: &BindingsIdx) -> Bindings {
+    fn build(self, idx: &BindingsIdx) -> Bindings<'a> {
         self.build_inner(&self.nodes[idx.0])
     }
 
-    fn build_inner(&self, link_nodes: &[LinkNode<Rc<BindingKind>>]) -> Bindings {
+    fn build_inner(&self, link_nodes: &[LinkNode<Rc<BindingKind<'a>>>]) -> Bindings<'a> {
         let mut bindings = Bindings::default();
         let mut nodes = Vec::new();
         self.collect_nodes(link_nodes, &mut nodes);
@@ -257,11 +264,11 @@ impl BindingsBuilder {
         bindings
     }
 
-    fn collect_nested_ref<'a>(
-        &'a self,
+    fn collect_nested_ref<'b>(
+        &'b self,
         id: usize,
         len: usize,
-        nested_refs: &mut Vec<&'a [LinkNode<Rc<BindingKind>>]>,
+        nested_refs: &mut Vec<&'b [LinkNode<Rc<BindingKind<'a>>>]>,
     ) {
         self.nested[id].iter().take(len).for_each(|it| match it {
             LinkNode::Node(id) => nested_refs.push(&self.nodes[*id]),
@@ -269,7 +276,7 @@ impl BindingsBuilder {
         });
     }
 
-    fn collect_nested(&self, idx: usize, nested_idx: usize, nested: &mut Vec<Bindings>) {
+    fn collect_nested(&self, idx: usize, nested_idx: usize, nested: &mut Vec<Bindings<'a>>) {
         let last = &self.nodes[idx];
         let mut nested_refs: Vec<&[_]> = Vec::new();
         self.nested[nested_idx].iter().for_each(|it| match *it {
@@ -280,17 +287,22 @@ impl BindingsBuilder {
         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>) {
+    fn collect_nodes_ref<'b>(
+        &'b self,
+        id: usize,
+        len: usize,
+        nodes: &mut Vec<&'b BindingKind<'a>>,
+    ) {
         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),
         });
     }
 
-    fn collect_nodes<'a>(
-        &'a self,
-        link_nodes: &'a [LinkNode<Rc<BindingKind>>],
-        nodes: &mut Vec<&'a BindingKind>,
+    fn collect_nodes<'b>(
+        &'b self,
+        link_nodes: &'b [LinkNode<Rc<BindingKind<'a>>>],
+        nodes: &mut Vec<&'b BindingKind<'a>>,
     ) {
         link_nodes.iter().for_each(|it| match it {
             LinkNode::Node(it) => nodes.push(it),
@@ -327,7 +339,7 @@ struct MatchState<'t> {
     bindings: BindingsIdx,
 
     /// Cached result of meta variable parsing
-    meta_result: Option<(TtIter<'t, Span>, ExpandResult<Option<Fragment>>)>,
+    meta_result: Option<(TtIter<'t, Span>, ExpandResult<Option<Fragment<'t>>>)>,
 
     /// Is error occurred in this state, will `poised` to "parent"
     is_error: bool,
@@ -355,8 +367,8 @@ struct MatchState<'t> {
 fn match_loop_inner<'t>(
     src: TtIter<'t, Span>,
     stack: &[TtIter<'t, Span>],
-    res: &mut Match,
-    bindings_builder: &mut BindingsBuilder,
+    res: &mut Match<'t>,
+    bindings_builder: &mut BindingsBuilder<'t>,
     cur_items: &mut SmallVec<[MatchState<'t>; 1]>,
     bb_items: &mut SmallVec<[MatchState<'t>; 1]>,
     next_items: &mut Vec<MatchState<'t>>,
@@ -463,7 +475,7 @@ fn match_loop_inner<'t>(
                 })
             }
             OpDelimited::Op(Op::Subtree { tokens, delimiter }) => {
-                if let Ok(subtree) = src.clone().expect_subtree() {
+                if let Ok((subtree, _)) = src.clone().expect_subtree() {
                     if subtree.delimiter.kind == delimiter.kind {
                         item.stack.push(item.dot);
                         item.dot = tokens.iter_delimited_with(*delimiter);
@@ -478,8 +490,8 @@ fn match_loop_inner<'t>(
                     match match_res.err {
                         None => {
                             // Some meta variables are optional (e.g. vis)
-                            if match_res.value.is_some() {
-                                item.meta_result = Some((fork, match_res));
+                            if !match_res.value.is_empty() {
+                                item.meta_result = Some((fork, match_res.map(Some)));
                                 try_push!(bb_items, item);
                             } else {
                                 bindings_builder.push_optional(&mut item.bindings, name);
@@ -489,15 +501,14 @@ fn match_loop_inner<'t>(
                         }
                         Some(err) => {
                             res.add_err(err);
-                            match match_res.value {
-                                Some(fragment) => bindings_builder.push_fragment(
+                            if !match_res.value.is_empty() {
+                                bindings_builder.push_fragment(
                                     &mut item.bindings,
                                     name,
-                                    fragment,
-                                ),
-                                None => {
-                                    bindings_builder.push_missing(&mut item.bindings, name, kind)
-                                }
+                                    match_res.value,
+                                )
+                            } else {
+                                bindings_builder.push_missing(&mut item.bindings, name, kind)
                             }
                             item.is_error = true;
                             error_items.push(item);
@@ -593,13 +604,13 @@ fn match_loop_inner<'t>(
                 stdx::never!("metavariable expression in lhs found");
             }
             OpDelimited::Open => {
-                if matches!(src.peek_n(0), Some(tt::TokenTree::Subtree(..))) {
+                if matches!(src.peek(), Some(TtElement::Subtree(..))) {
                     item.dot.next();
                     try_push!(next_items, item);
                 }
             }
             OpDelimited::Close => {
-                let is_delim_closed = src.peek_n(0).is_none() && !stack.is_empty();
+                let is_delim_closed = src.is_empty() && !stack.is_empty();
                 if is_delim_closed {
                     item.dot.next();
                     try_push!(next_items, item);
@@ -609,9 +620,13 @@ fn match_loop_inner<'t>(
     }
 }
 
-fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree<Span>, edition: Edition) -> Match {
-    let span = src.delimiter.delim_span();
-    let mut src = TtIter::new(src);
+fn match_loop<'t>(
+    pattern: &'t MetaTemplate,
+    src: &'t tt::TopSubtree<Span>,
+    edition: Edition,
+) -> Match<'t> {
+    let span = src.top_subtree().delimiter.delim_span();
+    let mut src = src.iter();
     let mut stack: SmallVec<[TtIter<'_, Span>; 1]> = SmallVec::new();
     let mut res = Match::default();
     let mut error_recover_item = None;
@@ -663,7 +678,7 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree<Span>, edition: Edition)
         // We need to do some post processing after the `match_loop_inner`.
         // If we reached the EOF, check that there is EXACTLY ONE possible matcher. Otherwise,
         // either the parse is ambiguous (which should never happen) or there is a syntax error.
-        if src.peek_n(0).is_none() && stack.is_empty() {
+        if src.is_empty() && stack.is_empty() {
             if let [state] = &*eof_items {
                 // remove all errors, because it is the correct answer !
                 res = Match::default();
@@ -687,11 +702,7 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree<Span>, edition: Edition)
             || !(bb_items.is_empty() || next_items.is_empty())
             || bb_items.len() > 1;
         if has_leftover_tokens {
-            res.unmatched_tts += src.len();
-            while let Some(it) = stack.pop() {
-                src = it;
-                res.unmatched_tts += src.len();
-            }
+            res.unmatched_tts += src.remaining().flat_tokens().len();
             res.add_err(ExpandError::new(span.open, ExpandErrorKind::LeftoverTokens));
 
             if let Some(error_recover_item) = error_recover_item {
@@ -714,9 +725,9 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree<Span>, edition: Edition)
                 }
             } else {
                 match src.next() {
-                    Some(tt::TokenTree::Subtree(subtree)) => {
+                    Some(TtElement::Subtree(_, subtree_iter)) => {
                         stack.push(src.clone());
-                        src = TtIter::new(subtree);
+                        src = subtree_iter;
                     }
                     None => {
                         if let Some(iter) = stack.pop() {
@@ -760,18 +771,16 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree<Span>, edition: Edition)
     }
 }
 
-fn match_meta_var(
+fn match_meta_var<'t>(
     kind: MetaVarKind,
-    input: &mut TtIter<'_, Span>,
+    input: &mut TtIter<'t, Span>,
     delim_span: DelimSpan<Span>,
     edition: Edition,
-) -> ExpandResult<Option<Fragment>> {
+) -> ExpandResult<Fragment<'t>> {
     let fragment = match kind {
         MetaVarKind::Path => {
             return expect_fragment(input, parser::PrefixEntryPoint::Path, edition, delim_span)
-                .map(|it| {
-                    it.map(|it| tt::TokenTree::subtree_or_wrap(it, delim_span)).map(Fragment::Path)
-                });
+                .map(Fragment::Path);
         }
         MetaVarKind::Expr(expr) => {
             // `expr_2021` should not match underscores, let expressions, or inline const.
@@ -782,8 +791,8 @@ fn match_meta_var(
             // rustc [explicitly checks the next token][1].
             // [0]: https://github.com/rust-lang/rust/issues/86730
             // [1]: https://github.com/rust-lang/rust/blob/f0c4da499/compiler/rustc_expand/src/mbe/macro_parser.rs#L576
-            match input.peek_n(0) {
-                Some(tt::TokenTree::Leaf(tt::Leaf::Ident(it))) => {
+            match input.peek() {
+                Some(TtElement::Leaf(tt::Leaf::Ident(it))) => {
                     let is_err = if it.is_raw.no() && matches!(expr, ExprKind::Expr2021) {
                         it.sym == sym::underscore || it.sym == sym::let_ || it.sym == sym::const_
                     } else {
@@ -799,34 +808,15 @@ fn match_meta_var(
                 _ => {}
             };
             return expect_fragment(input, parser::PrefixEntryPoint::Expr, edition, delim_span)
-                .map(|tt| {
-                    tt.map(|tt| match tt {
-                        tt::TokenTree::Leaf(leaf) => tt::Subtree {
-                            delimiter: tt::Delimiter::invisible_spanned(*leaf.span()),
-                            token_trees: Box::new([leaf.into()]),
-                        },
-                        tt::TokenTree::Subtree(mut s) => {
-                            if s.delimiter.kind == tt::DelimiterKind::Invisible {
-                                s.delimiter.kind = tt::DelimiterKind::Parenthesis;
-                            }
-                            s
-                        }
-                    })
-                    .map(Fragment::Expr)
-                });
+                .map(Fragment::Expr);
         }
         MetaVarKind::Ident | MetaVarKind::Tt | MetaVarKind::Lifetime | MetaVarKind::Literal => {
             let span = input.next_span();
-            let tt_result = match kind {
-                MetaVarKind::Ident => input
-                    .expect_ident()
-                    .map(|ident| tt::Leaf::from(ident.clone()).into())
-                    .map_err(|()| {
-                        ExpandError::binding_error(
-                            span.unwrap_or(delim_span.close),
-                            "expected ident",
-                        )
-                    }),
+            let savepoint = input.savepoint();
+            let err = match kind {
+                MetaVarKind::Ident => input.expect_ident().map(drop).map_err(|()| {
+                    ExpandError::binding_error(span.unwrap_or(delim_span.close), "expected ident")
+                }),
                 MetaVarKind::Tt => expect_tt(input).map_err(|()| {
                     ExpandError::binding_error(
                         span.unwrap_or(delim_span.close),
@@ -840,29 +830,19 @@ fn match_meta_var(
                     )
                 }),
                 MetaVarKind::Literal => {
-                    let neg = eat_char(input, '-');
-                    input
-                        .expect_literal()
-                        .map(|literal| {
-                            let lit = literal.clone();
-                            match neg {
-                                None => lit.into(),
-                                Some(neg) => tt::TokenTree::Subtree(tt::Subtree {
-                                    delimiter: tt::Delimiter::invisible_spanned(*literal.span()),
-                                    token_trees: Box::new([neg, lit.into()]),
-                                }),
-                            }
-                        })
-                        .map_err(|()| {
-                            ExpandError::binding_error(
-                                span.unwrap_or(delim_span.close),
-                                "expected literal",
-                            )
-                        })
+                    eat_char(input, '-');
+                    input.expect_literal().map(drop).map_err(|()| {
+                        ExpandError::binding_error(
+                            span.unwrap_or(delim_span.close),
+                            "expected literal",
+                        )
+                    })
                 }
                 _ => unreachable!(),
-            };
-            return tt_result.map(|it| Some(Fragment::Tokens(it))).into();
+            }
+            .err();
+            let tt_result = input.from_savepoint(savepoint);
+            return ValueResult { value: Fragment::Tokens(tt_result), err };
         }
         MetaVarKind::Ty => parser::PrefixEntryPoint::Ty,
         MetaVarKind::Pat => parser::PrefixEntryPoint::PatTop,
@@ -873,7 +853,7 @@ fn match_meta_var(
         MetaVarKind::Item => parser::PrefixEntryPoint::Item,
         MetaVarKind::Vis => parser::PrefixEntryPoint::Vis,
     };
-    expect_fragment(input, fragment, edition, delim_span).map(|it| it.map(Fragment::Tokens))
+    expect_fragment(input, fragment, edition, delim_span).map(Fragment::Tokens)
 }
 
 fn collect_vars(collector_fun: &mut impl FnMut(Symbol), pattern: &MetaTemplate) {
@@ -990,54 +970,31 @@ fn expect_separator<S: Copy>(iter: &mut TtIter<'_, S>, separator: &Separator) ->
     ok
 }
 
-fn expect_tt<S: Copy>(iter: &mut TtIter<'_, S>) -> Result<tt::TokenTree<S>, ()> {
-    if let Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) = iter.peek_n(0) {
+fn expect_tt<S: Copy>(iter: &mut TtIter<'_, S>) -> Result<(), ()> {
+    if let Some(TtElement::Leaf(tt::Leaf::Punct(punct))) = iter.peek() {
         if punct.char == '\'' {
-            expect_lifetime(iter)
+            expect_lifetime(iter)?;
         } else {
-            let puncts = iter.expect_glued_punct()?;
-            let delimiter = tt::Delimiter {
-                open: puncts.first().unwrap().span,
-                close: puncts.last().unwrap().span,
-                kind: tt::DelimiterKind::Invisible,
-            };
-            let token_trees = puncts.into_iter().map(|p| tt::Leaf::Punct(p).into()).collect();
-            Ok(tt::TokenTree::Subtree(tt::Subtree { delimiter, token_trees }))
+            iter.expect_glued_punct()?;
         }
     } else {
-        iter.next().ok_or(()).cloned()
+        iter.next().ok_or(())?;
     }
+    Ok(())
 }
 
-fn expect_lifetime<S: Copy>(iter: &mut TtIter<'_, S>) -> Result<tt::TokenTree<S>, ()> {
+fn expect_lifetime<S: Copy>(iter: &mut TtIter<'_, S>) -> Result<(), ()> {
     let punct = iter.expect_single_punct()?;
     if punct.char != '\'' {
         return Err(());
     }
-    let ident = iter.expect_ident_or_underscore()?;
-
-    Ok(tt::Subtree {
-        delimiter: tt::Delimiter {
-            open: punct.span,
-            close: ident.span,
-            kind: tt::DelimiterKind::Invisible,
-        },
-        token_trees: Box::new([
-            tt::Leaf::Punct(*punct).into(),
-            tt::Leaf::Ident(ident.clone()).into(),
-        ]),
-    }
-    .into())
+    iter.expect_ident_or_underscore()?;
+    Ok(())
 }
 
-fn eat_char<S: Copy>(iter: &mut TtIter<'_, S>, c: char) -> Option<tt::TokenTree<S>> {
-    let mut fork = iter.clone();
-    match fork.expect_char(c) {
-        Ok(_) => {
-            let tt = iter.next().cloned();
-            *iter = fork;
-            tt
-        }
-        Err(_) => None,
+fn eat_char<S: Copy>(iter: &mut TtIter<'_, S>, c: char) {
+    if matches!(iter.peek(), Some(TtElement::Leaf(tt::Leaf::Punct(tt::Punct { char, .. }))) if *char == c)
+    {
+        iter.next().expect("already peeked");
     }
 }
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 1db2f35d262..9255c5a6899 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/expander/transcriber.rs
@@ -3,7 +3,7 @@
 
 use intern::{sym, Symbol};
 use span::{Edition, Span};
-use tt::Delimiter;
+use tt::{iter::TtElement, Delimiter, TopSubtreeBuilder};
 
 use crate::{
     expander::{Binding, Bindings, Fragment},
@@ -11,8 +11,8 @@ use crate::{
     ExpandError, ExpandErrorKind, ExpandResult, MetaTemplate,
 };
 
-impl Bindings {
-    fn get(&self, name: &Symbol, span: Span) -> Result<&Binding, ExpandError> {
+impl<'t> Bindings<'t> {
+    fn get(&self, name: &Symbol, span: Span) -> Result<&Binding<'t>, ExpandError> {
         match self.inner.get(name) {
             Some(binding) => Ok(binding),
             None => Err(ExpandError::new(
@@ -28,7 +28,7 @@ impl Bindings {
         mut span: Span,
         nesting: &mut [NestingState],
         marker: impl Fn(&mut Span),
-    ) -> Result<Fragment, ExpandError> {
+    ) -> Result<Fragment<'t>, ExpandError> {
         macro_rules! binding_err {
             ($($arg:tt)*) => { ExpandError::binding_error(span, format!($($arg)*)) };
         }
@@ -50,86 +50,61 @@ impl Bindings {
             };
         }
         match b {
-            Binding::Fragment(f @ (Fragment::Path(sub) | Fragment::Expr(sub))) => {
-                let tt::Subtree { delimiter, token_trees } = sub;
-                marker(&mut span);
-                let subtree = tt::Subtree {
-                    delimiter: tt::Delimiter {
-                        // FIXME split span
-                        open: span,
-                        close: span,
-                        kind: delimiter.kind,
-                    },
-                    token_trees: token_trees.clone(),
-                };
-                Ok(match f {
-                    Fragment::Tokens(_) | Fragment::Empty => unreachable!(),
-                    Fragment::Expr(_) => Fragment::Expr,
-                    Fragment::Path(_) => Fragment::Path,
-                }(subtree))
-            }
-            Binding::Fragment(it @ (Fragment::Tokens(_) | Fragment::Empty)) => Ok(it.clone()),
+            Binding::Fragment(f) => Ok(f.clone()),
             // emit some reasonable default expansion for missing bindings,
             // this gives better recovery than emitting the `$fragment-name` verbatim
             Binding::Missing(it) => Ok({
                 marker(&mut span);
+                let mut builder = TopSubtreeBuilder::new(tt::Delimiter::invisible_spanned(span));
                 match it {
                     MetaVarKind::Stmt => {
-                        Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct {
+                        builder.push(tt::Leaf::Punct(tt::Punct {
                             span,
                             char: ';',
                             spacing: tt::Spacing::Alone,
-                        })))
+                        }));
                     }
-                    MetaVarKind::Block => Fragment::Tokens(tt::TokenTree::Subtree(tt::Subtree {
-                        delimiter: tt::Delimiter {
-                            open: span,
-                            close: span,
-                            kind: tt::DelimiterKind::Brace,
-                        },
-                        token_trees: Box::new([]),
-                    })),
-                    // FIXME: Meta and Item should get proper defaults
-                    MetaVarKind::Meta | MetaVarKind::Item | MetaVarKind::Tt | MetaVarKind::Vis => {
-                        Fragment::Empty
+                    MetaVarKind::Block => {
+                        builder.open(tt::DelimiterKind::Brace, span);
+                        builder.close(span);
                     }
+                    // FIXME: Meta and Item should get proper defaults
+                    MetaVarKind::Meta | MetaVarKind::Item | MetaVarKind::Tt | MetaVarKind::Vis => {}
                     MetaVarKind::Path
                     | MetaVarKind::Ty
                     | MetaVarKind::Pat
                     | MetaVarKind::PatParam
                     | MetaVarKind::Expr(_)
                     | MetaVarKind::Ident => {
-                        Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
+                        builder.push(tt::Leaf::Ident(tt::Ident {
                             sym: sym::missing.clone(),
                             span,
                             is_raw: tt::IdentIsRaw::No,
-                        })))
+                        }));
                     }
                     MetaVarKind::Lifetime => {
-                        Fragment::Tokens(tt::TokenTree::Subtree(tt::Subtree {
-                            delimiter: tt::Delimiter::invisible_spanned(span),
-                            token_trees: Box::new([
-                                tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct {
-                                    char: '\'',
-                                    span,
-                                    spacing: tt::Spacing::Joint,
-                                })),
-                                tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
-                                    sym: sym::missing.clone(),
-                                    span,
-                                    is_raw: tt::IdentIsRaw::No,
-                                })),
-                            ]),
-                        }))
+                        builder.extend([
+                            tt::Leaf::Punct(tt::Punct {
+                                char: '\'',
+                                span,
+                                spacing: tt::Spacing::Joint,
+                            }),
+                            tt::Leaf::Ident(tt::Ident {
+                                sym: sym::missing.clone(),
+                                span,
+                                is_raw: tt::IdentIsRaw::No,
+                            }),
+                        ]);
                     }
                     MetaVarKind::Literal => {
-                        Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
+                        builder.push(tt::Leaf::Ident(tt::Ident {
                             sym: sym::missing.clone(),
                             span,
                             is_raw: tt::IdentIsRaw::No,
-                        })))
+                        }));
                     }
                 }
+                Fragment::TokensOwned(builder.build())
             }),
             Binding::Nested(_) => {
                 Err(binding_err!("expected simple binding, found nested binding `{name}`"))
@@ -143,13 +118,13 @@ impl Bindings {
 
 pub(super) fn transcribe(
     template: &MetaTemplate,
-    bindings: &Bindings,
+    bindings: &Bindings<'_>,
     marker: impl Fn(&mut Span) + Copy,
     call_site: Span,
-) -> ExpandResult<tt::Subtree<Span>> {
+) -> ExpandResult<tt::TopSubtree<Span>> {
     let mut ctx = ExpandCtx { bindings, nesting: Vec::new(), call_site };
-    let mut arena: Vec<tt::TokenTree<Span>> = Vec::new();
-    expand_subtree(&mut ctx, template, None, &mut arena, marker)
+    let mut builder = tt::TopSubtreeBuilder::new(tt::Delimiter::invisible_spanned(ctx.call_site));
+    expand_subtree(&mut ctx, template, &mut builder, marker).map(|()| builder.build())
 }
 
 #[derive(Debug)]
@@ -165,103 +140,97 @@ struct NestingState {
 
 #[derive(Debug)]
 struct ExpandCtx<'a> {
-    bindings: &'a Bindings,
+    bindings: &'a Bindings<'a>,
     nesting: Vec<NestingState>,
     call_site: Span,
 }
 
-fn expand_subtree(
+fn expand_subtree_with_delimiter(
     ctx: &mut ExpandCtx<'_>,
     template: &MetaTemplate,
+    builder: &mut tt::TopSubtreeBuilder<Span>,
     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();
+) -> ExpandResult<()> {
+    let delimiter = delimiter.unwrap_or_else(|| tt::Delimiter::invisible_spanned(ctx.call_site));
+    builder.open(delimiter.kind, delimiter.open);
+    let result = expand_subtree(ctx, template, builder, marker);
+    builder.close(delimiter.close);
+    result
+}
+
+fn expand_subtree(
+    ctx: &mut ExpandCtx<'_>,
+    template: &MetaTemplate,
+    builder: &mut tt::TopSubtreeBuilder<Span>,
+    marker: impl Fn(&mut Span) + Copy,
+) -> ExpandResult<()> {
     let mut err = None;
     'ops: for op in template.iter() {
         match op {
-            Op::Literal(it) => arena.push(
-                tt::Leaf::from({
-                    let mut it = it.clone();
-                    marker(&mut it.span);
-                    it
-                })
-                .into(),
-            ),
-            Op::Ident(it) => arena.push(
-                tt::Leaf::from({
-                    let mut it = it.clone();
-                    marker(&mut it.span);
-                    it
-                })
-                .into(),
-            ),
+            Op::Literal(it) => builder.push(tt::Leaf::from({
+                let mut it = it.clone();
+                marker(&mut it.span);
+                it
+            })),
+            Op::Ident(it) => builder.push(tt::Leaf::from({
+                let mut it = it.clone();
+                marker(&mut it.span);
+                it
+            })),
             Op::Punct(puncts) => {
-                for punct in puncts.as_slice() {
-                    arena.push(
-                        tt::Leaf::from({
-                            let mut it = *punct;
-                            marker(&mut it.span);
-                            it
-                        })
-                        .into(),
-                    );
-                }
+                builder.extend(puncts.iter().map(|punct| {
+                    tt::Leaf::from({
+                        let mut it = *punct;
+                        marker(&mut it.span);
+                        it
+                    })
+                }));
             }
             Op::Subtree { tokens, delimiter } => {
                 let mut delimiter = *delimiter;
                 marker(&mut delimiter.open);
                 marker(&mut delimiter.close);
-                let ExpandResult { value: tt, err: e } =
-                    expand_subtree(ctx, tokens, Some(delimiter), arena, marker);
+                let ExpandResult { value: (), err: e } =
+                    expand_subtree_with_delimiter(ctx, tokens, builder, Some(delimiter), marker);
                 err = err.or(e);
-                arena.push(tt.into());
             }
             Op::Var { name, id, .. } => {
-                let ExpandResult { value: fragment, err: e } = expand_var(ctx, name, *id, marker);
+                let ExpandResult { value: (), err: e } =
+                    expand_var(ctx, name, *id, builder, marker);
                 err = err.or(e);
-                push_fragment(ctx, arena, fragment);
             }
             Op::Repeat { tokens: subtree, kind, separator } => {
-                let ExpandResult { value: fragment, err: e } =
-                    expand_repeat(ctx, subtree, *kind, separator.as_deref(), arena, marker);
+                let ExpandResult { value: (), err: e } =
+                    expand_repeat(ctx, subtree, *kind, separator.as_deref(), builder, marker);
                 err = err.or(e);
-                push_fragment(ctx, arena, fragment)
             }
             Op::Ignore { name, id } => {
                 // Expand the variable, but ignore the result. This registers the repetition count.
                 // FIXME: Any emitted errors are dropped.
-                expand_var(ctx, name, *id, marker);
+                let _ = ctx.bindings.get_fragment(name, *id, &mut ctx.nesting, marker);
             }
             Op::Index { depth } => {
                 let index =
                     ctx.nesting.get(ctx.nesting.len() - 1 - depth).map_or(0, |nest| nest.idx);
-                arena.push(
-                    tt::Leaf::Literal(tt::Literal {
-                        symbol: Symbol::integer(index),
-                        span: ctx.call_site,
-                        kind: tt::LitKind::Integer,
-                        suffix: None,
-                    })
-                    .into(),
-                );
+                builder.push(tt::Leaf::Literal(tt::Literal {
+                    symbol: Symbol::integer(index),
+                    span: ctx.call_site,
+                    kind: tt::LitKind::Integer,
+                    suffix: None,
+                }));
             }
             Op::Len { depth } => {
                 let length = ctx.nesting.get(ctx.nesting.len() - 1 - depth).map_or(0, |_nest| {
                     // FIXME: to be implemented
                     0
                 });
-                arena.push(
-                    tt::Leaf::Literal(tt::Literal {
-                        symbol: Symbol::integer(length),
-                        span: ctx.call_site,
-                        kind: tt::LitKind::Integer,
-                        suffix: None,
-                    })
-                    .into(),
-                );
+                builder.push(tt::Leaf::Literal(tt::Literal {
+                    symbol: Symbol::integer(length),
+                    span: ctx.call_site,
+                    kind: tt::LitKind::Integer,
+                    suffix: None,
+                }));
             }
             Op::Count { name, depth } => {
                 let mut binding = match ctx.bindings.get(name, ctx.call_site) {
@@ -302,15 +271,12 @@ fn expand_subtree(
 
                 let res = count(binding, 0, depth.unwrap_or(0));
 
-                arena.push(
-                    tt::Leaf::Literal(tt::Literal {
-                        symbol: Symbol::integer(res),
-                        span: ctx.call_site,
-                        suffix: None,
-                        kind: tt::LitKind::Integer,
-                    })
-                    .into(),
-                );
+                builder.push(tt::Leaf::Literal(tt::Literal {
+                    symbol: Symbol::integer(res),
+                    span: ctx.call_site,
+                    suffix: None,
+                    kind: tt::LitKind::Integer,
+                }));
             }
             Op::Concat { elements, span: concat_span } => {
                 let mut concatenated = String::new();
@@ -342,11 +308,22 @@ fn expand_subtree(
                                     continue;
                                 }
                             };
-                            let value = match &var_value {
-                                Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Ident(ident))) => {
+                            let values = match &var_value {
+                                Fragment::Tokens(tokens) => {
+                                    let mut iter = tokens.iter();
+                                    (iter.next(), iter.next())
+                                }
+                                Fragment::TokensOwned(tokens) => {
+                                    let mut iter = tokens.iter();
+                                    (iter.next(), iter.next())
+                                }
+                                _ => (None, None),
+                            };
+                            let value = match values {
+                                (Some(TtElement::Leaf(tt::Leaf::Ident(ident))), None) => {
                                     ident.sym.as_str()
                                 }
-                                Fragment::Tokens(tt::TokenTree::Leaf(tt::Leaf::Literal(lit))) => {
+                                (Some(TtElement::Leaf(tt::Leaf::Literal(lit))), None) => {
                                     lit.symbol.as_str()
                                 }
                                 _ => {
@@ -382,36 +359,53 @@ fn expand_subtree(
                 let needs_raw =
                     parser::SyntaxKind::from_keyword(&concatenated, Edition::LATEST).is_some();
                 let is_raw = if needs_raw { tt::IdentIsRaw::Yes } else { tt::IdentIsRaw::No };
-                arena.push(tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
+                builder.push(tt::Leaf::Ident(tt::Ident {
                     is_raw,
                     span: result_span,
                     sym: Symbol::intern(&concatenated),
-                })));
+                }));
             }
         }
     }
-    // drain the elements added in this instance of expand_subtree
-    let tts = arena.drain(start_elements..).collect();
-    ExpandResult {
-        value: tt::Subtree {
-            delimiter: delimiter.unwrap_or_else(|| tt::Delimiter::invisible_spanned(ctx.call_site)),
-            token_trees: tts,
-        },
-        err,
-    }
+    ExpandResult { value: (), err }
 }
 
 fn expand_var(
     ctx: &mut ExpandCtx<'_>,
     v: &Symbol,
     id: Span,
-    marker: impl Fn(&mut Span),
-) -> ExpandResult<Fragment> {
+    builder: &mut tt::TopSubtreeBuilder<Span>,
+    marker: impl Fn(&mut Span) + Copy,
+) -> ExpandResult<()> {
     // We already handle $crate case in mbe parser
     debug_assert!(*v != sym::crate_);
 
     match ctx.bindings.get_fragment(v, id, &mut ctx.nesting, marker) {
-        Ok(it) => ExpandResult::ok(it),
+        Ok(fragment) => {
+            match fragment {
+                Fragment::Tokens(tt) => builder.extend_with_tt(tt.strip_invisible()),
+                Fragment::TokensOwned(tt) => builder.extend_with_tt(tt.view().strip_invisible()),
+                Fragment::Expr(sub) => {
+                    let sub = sub.strip_invisible();
+                    let mut span = id;
+                    marker(&mut span);
+                    let wrap_in_parens = !matches!(sub.flat_tokens(), [tt::TokenTree::Leaf(_)])
+                        && sub.try_into_subtree().is_none_or(|it| {
+                            it.top_subtree().delimiter.kind == tt::DelimiterKind::Invisible
+                        });
+                    if wrap_in_parens {
+                        builder.open(tt::DelimiterKind::Parenthesis, span);
+                    }
+                    builder.extend_with_tt(sub);
+                    if wrap_in_parens {
+                        builder.close(span);
+                    }
+                }
+                Fragment::Path(tt) => fix_up_and_push_path_tt(ctx, builder, tt),
+                Fragment::Empty => (),
+            };
+            ExpandResult::ok(())
+        }
         Err(e) if matches!(e.inner.1, ExpandErrorKind::UnresolvedBinding(_)) => {
             // Note that it is possible to have a `$var` inside a macro which is not bound.
             // For example:
@@ -426,29 +420,13 @@ fn expand_var(
             //     }
             // ```
             // We just treat it a normal tokens
-            let tt = tt::Subtree {
-                delimiter: tt::Delimiter::invisible_spanned(id),
-                token_trees: Box::new([
-                    tt::Leaf::from(tt::Punct { char: '$', spacing: tt::Spacing::Alone, span: id })
-                        .into(),
-                    tt::Leaf::from(tt::Ident {
-                        sym: v.clone(),
-                        span: id,
-                        is_raw: tt::IdentIsRaw::No,
-                    })
-                    .into(),
-                ]),
-            }
-            .into();
-            ExpandResult::ok(Fragment::Tokens(tt))
+            builder.extend([
+                tt::Leaf::from(tt::Punct { char: '$', spacing: tt::Spacing::Alone, span: id }),
+                tt::Leaf::from(tt::Ident { sym: v.clone(), span: id, is_raw: tt::IdentIsRaw::No }),
+            ]);
+            ExpandResult::ok(())
         }
-        Err(e) => ExpandResult {
-            value: Fragment::Tokens(tt::TokenTree::Subtree(tt::Subtree::empty(tt::DelimSpan {
-                open: ctx.call_site,
-                close: ctx.call_site,
-            }))),
-            err: Some(e),
-        },
+        Err(e) => ExpandResult::only_err(e),
     }
 }
 
@@ -457,21 +435,20 @@ fn expand_repeat(
     template: &MetaTemplate,
     kind: RepeatKind,
     separator: Option<&Separator>,
-    arena: &mut Vec<tt::TokenTree<Span>>,
+    builder: &mut tt::TopSubtreeBuilder<Span>,
     marker: impl Fn(&mut Span) + Copy,
-) -> ExpandResult<Fragment> {
-    let mut buf: Vec<tt::TokenTree<Span>> = Vec::new();
+) -> ExpandResult<()> {
     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
     let limit = 65536;
-    let mut has_seps = 0;
     let mut counter = 0;
     let mut err = None;
 
+    let mut restore_point = builder.restore_point();
     loop {
-        let ExpandResult { value: mut t, err: e } =
-            expand_subtree(ctx, template, None, arena, marker);
+        let ExpandResult { value: (), err: e } =
+            expand_subtree_with_delimiter(ctx, template, builder, None, marker);
         let nesting_state = ctx.nesting.last_mut().unwrap();
         if nesting_state.at_end || !nesting_state.hit {
             break;
@@ -479,23 +456,14 @@ fn expand_repeat(
         nesting_state.idx += 1;
         nesting_state.hit = false;
 
+        builder.remove_last_subtree_if_invisible();
+
+        restore_point = builder.restore_point();
+
         counter += 1;
         if counter == limit {
-            tracing::warn!(
-                "expand_tt in repeat pattern exceed limit => {:#?}\n{:#?}",
-                template,
-                ctx
-            );
-            return ExpandResult {
-                value: Fragment::Tokens(
-                    tt::Subtree {
-                        delimiter: tt::Delimiter::invisible_spanned(ctx.call_site),
-                        token_trees: Box::new([]),
-                    }
-                    .into(),
-                ),
-                err: Some(ExpandError::new(ctx.call_site, ExpandErrorKind::LimitExceeded)),
-            };
+            err = Some(ExpandError::new(ctx.call_site, ExpandErrorKind::LimitExceeded));
+            break;
         }
 
         if e.is_some() {
@@ -503,24 +471,14 @@ fn expand_repeat(
             continue;
         }
 
-        t.delimiter.kind = tt::DelimiterKind::Invisible;
-        push_subtree(&mut buf, t);
-
         if let Some(sep) = separator {
-            has_seps = match sep {
-                Separator::Ident(ident) => {
-                    buf.push(tt::Leaf::from(ident.clone()).into());
-                    1
-                }
-                Separator::Literal(lit) => {
-                    buf.push(tt::Leaf::from(lit.clone()).into());
-                    1
-                }
+            match sep {
+                Separator::Ident(ident) => builder.push(tt::Leaf::from(ident.clone())),
+                Separator::Literal(lit) => builder.push(tt::Leaf::from(lit.clone())),
                 Separator::Puncts(puncts) => {
                     for &punct in puncts {
-                        buf.push(tt::Leaf::from(punct).into());
+                        builder.push(tt::Leaf::from(punct));
                     }
-                    puncts.len()
                 }
             };
         }
@@ -529,46 +487,18 @@ fn expand_repeat(
             break;
         }
     }
+    // Lose the last separator and last after-the-end round.
+    builder.restore(restore_point);
 
     ctx.nesting.pop().unwrap();
-    for _ in 0..has_seps {
-        buf.pop();
-    }
 
     // Check if it is a single token subtree without any delimiter
     // e.g {Delimiter:None> ['>'] /Delimiter:None>}
-    let tt = tt::Subtree {
-        delimiter: tt::Delimiter::invisible_spanned(ctx.call_site),
-        token_trees: buf.into_boxed_slice(),
-    };
-
-    if RepeatKind::OneOrMore == kind && counter == 0 {
-        let span = tt.delimiter.open;
-        return ExpandResult {
-            value: Fragment::Tokens(tt.into()),
-            err: Some(ExpandError::new(span, ExpandErrorKind::UnexpectedToken)),
-        };
-    }
-    ExpandResult { value: Fragment::Tokens(tt.into()), err }
-}
 
-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) => {
-            push_subtree(buf, sub);
-        }
-        Fragment::Path(tt) => fix_up_and_push_path_tt(ctx, buf, tt),
-        Fragment::Tokens(tt) => buf.push(tt),
-        Fragment::Empty => (),
-    }
-}
-
-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()),
+    if RepeatKind::OneOrMore == kind && counter == 0 && err.is_none() {
+        err = Some(ExpandError::new(ctx.call_site, ExpandErrorKind::UnexpectedToken));
     }
+    ExpandResult { value: (), err }
 }
 
 /// Inserts the path separator `::` between an identifier and its following generic
@@ -576,47 +506,45 @@ fn push_subtree(buf: &mut Vec<tt::TokenTree<Span>>, tt: tt::Subtree<Span>) {
 /// we need this fixup.
 fn fix_up_and_push_path_tt(
     ctx: &ExpandCtx<'_>,
-    buf: &mut Vec<tt::TokenTree<Span>>,
-    subtree: tt::Subtree<Span>,
+    builder: &mut tt::TopSubtreeBuilder<Span>,
+    subtree: tt::TokenTreesView<'_, Span>,
 ) {
-    stdx::always!(matches!(subtree.delimiter.kind, tt::DelimiterKind::Invisible));
     let mut prev_was_ident = false;
     // Note that we only need to fix up the top-level `TokenTree`s because the
     // context of the paths in the descendant `Subtree`s won't be changed by the
     // mbe transcription.
-    for tt in Vec::from(subtree.token_trees) {
+    let mut iter = subtree.iter();
+    while let Some(tt) = iter.next_as_view() {
         if prev_was_ident {
             // Pedantically, `(T) -> U` in `FnOnce(T) -> U` is treated as a generic
             // argument list and thus needs `::` between it and `FnOnce`. However in
             // today's Rust this type of path *semantically* cannot appear as a
             // top-level expression-context path, so we can safely ignore it.
-            if let tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: '<', .. })) = tt {
-                buf.push(
+            if let [tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: '<', .. }))] =
+                tt.flat_tokens()
+            {
+                builder.extend([
                     tt::Leaf::Punct(tt::Punct {
                         char: ':',
                         spacing: tt::Spacing::Joint,
                         span: ctx.call_site,
-                    })
-                    .into(),
-                );
-                buf.push(
+                    }),
                     tt::Leaf::Punct(tt::Punct {
                         char: ':',
                         spacing: tt::Spacing::Alone,
                         span: ctx.call_site,
-                    })
-                    .into(),
-                );
+                    }),
+                ]);
             }
         }
-        prev_was_ident = matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Ident(_)));
-        buf.push(tt);
+        prev_was_ident = matches!(tt.flat_tokens(), [tt::TokenTree::Leaf(tt::Leaf::Ident(_))]);
+        builder.extend_with_tt(tt);
     }
 }
 
 /// Handles `${count(t, depth)}`. `our_depth` is the recursion depth and `count_depth` is the depth
 /// defined by the metavar expression.
-fn count(binding: &Binding, depth_curr: usize, depth_max: usize) -> usize {
+fn count(binding: &Binding<'_>, depth_curr: usize, depth_max: usize) -> usize {
     match binding {
         Binding::Nested(bs) => {
             if depth_curr == depth_max {
diff --git a/src/tools/rust-analyzer/crates/mbe/src/lib.rs b/src/tools/rust-analyzer/crates/mbe/src/lib.rs
index ca10a2be273..6abf56d4b37 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/lib.rs
@@ -148,17 +148,17 @@ impl DeclarativeMacro {
 
     /// The old, `macro_rules! m {}` flavor.
     pub fn parse_macro_rules(
-        tt: &tt::Subtree<Span>,
+        tt: &tt::TopSubtree<Span>,
         ctx_edition: impl Copy + Fn(SyntaxContextId) -> Edition,
     ) -> DeclarativeMacro {
         // Note: this parsing can be implemented using mbe machinery itself, by
         // matching against `$($lhs:tt => $rhs:tt);*` pattern, but implementing
         // manually seems easier.
-        let mut src = TtIter::new(tt);
+        let mut src = tt.iter();
         let mut rules = Vec::new();
         let mut err = None;
 
-        while src.len() > 0 {
+        while !src.is_empty() {
             let rule = match Rule::parse(ctx_edition, &mut src) {
                 Ok(it) => it,
                 Err(e) => {
@@ -168,7 +168,7 @@ impl DeclarativeMacro {
             };
             rules.push(rule);
             if let Err(()) = src.expect_char(';') {
-                if src.len() > 0 {
+                if !src.is_empty() {
                     err = Some(Box::new(ParseError::expected("expected `;`")));
                 }
                 break;
@@ -187,8 +187,8 @@ impl DeclarativeMacro {
 
     /// The new, unstable `macro m {}` flavor.
     pub fn parse_macro2(
-        args: Option<&tt::Subtree<Span>>,
-        body: &tt::Subtree<Span>,
+        args: Option<&tt::TopSubtree<Span>>,
+        body: &tt::TopSubtree<Span>,
         ctx_edition: impl Copy + Fn(SyntaxContextId) -> Edition,
     ) -> DeclarativeMacro {
         let mut rules = Vec::new();
@@ -198,8 +198,8 @@ impl DeclarativeMacro {
             cov_mark::hit!(parse_macro_def_simple);
 
             let rule = (|| {
-                let lhs = MetaTemplate::parse_pattern(ctx_edition, args)?;
-                let rhs = MetaTemplate::parse_template(ctx_edition, body)?;
+                let lhs = MetaTemplate::parse_pattern(ctx_edition, args.iter())?;
+                let rhs = MetaTemplate::parse_template(ctx_edition, body.iter())?;
 
                 Ok(crate::Rule { lhs, rhs })
             })();
@@ -210,8 +210,8 @@ impl DeclarativeMacro {
             }
         } else {
             cov_mark::hit!(parse_macro_def_rules);
-            let mut src = TtIter::new(body);
-            while src.len() > 0 {
+            let mut src = body.iter();
+            while !src.is_empty() {
                 let rule = match Rule::parse(ctx_edition, &mut src) {
                     Ok(it) => it,
                     Err(e) => {
@@ -221,7 +221,7 @@ impl DeclarativeMacro {
                 };
                 rules.push(rule);
                 if let Err(()) = src.expect_any_char(&[';', ',']) {
-                    if src.len() > 0 {
+                    if !src.is_empty() {
                         err = Some(Box::new(ParseError::expected(
                             "expected `;` or `,` to delimit rules",
                         )));
@@ -251,11 +251,11 @@ impl DeclarativeMacro {
 
     pub fn expand(
         &self,
-        tt: &tt::Subtree<Span>,
+        tt: &tt::TopSubtree<Span>,
         marker: impl Fn(&mut Span) + Copy,
         call_site: Span,
         def_site_edition: Edition,
-    ) -> ExpandResult<(tt::Subtree<Span>, MatchedArmIndex)> {
+    ) -> ExpandResult<(tt::TopSubtree<Span>, MatchedArmIndex)> {
         expander::expand_rules(&self.rules, tt, marker, call_site, def_site_edition)
     }
 }
@@ -265,10 +265,12 @@ impl Rule {
         edition: impl Copy + Fn(SyntaxContextId) -> Edition,
         src: &mut TtIter<'_, Span>,
     ) -> Result<Self, ParseError> {
-        let lhs = src.expect_subtree().map_err(|()| ParseError::expected("expected subtree"))?;
+        let (_, lhs) =
+            src.expect_subtree().map_err(|()| ParseError::expected("expected subtree"))?;
         src.expect_char('=').map_err(|()| ParseError::expected("expected `=`"))?;
         src.expect_char('>').map_err(|()| ParseError::expected("expected `>`"))?;
-        let rhs = src.expect_subtree().map_err(|()| ParseError::expected("expected subtree"))?;
+        let (_, rhs) =
+            src.expect_subtree().map_err(|()| ParseError::expected("expected subtree"))?;
 
         let lhs = MetaTemplate::parse_pattern(edition, lhs)?;
         let rhs = MetaTemplate::parse_template(edition, rhs)?;
@@ -359,17 +361,17 @@ impl<T: Default, E> From<Result<T, E>> for ValueResult<T, E> {
     }
 }
 
-pub fn expect_fragment(
-    tt_iter: &mut TtIter<'_, Span>,
+pub fn expect_fragment<'t>(
+    tt_iter: &mut TtIter<'t, Span>,
     entry_point: ::parser::PrefixEntryPoint,
     edition: ::parser::Edition,
     delim_span: DelimSpan<Span>,
-) -> ExpandResult<Option<tt::TokenTree<Span>>> {
+) -> ExpandResult<tt::TokenTreesView<'t, Span>> {
     use ::parser;
-    let buffer = tt::buffer::TokenBuffer::from_tokens(tt_iter.as_slice());
-    let parser_input = to_parser_input(edition, &buffer);
+    let buffer = tt_iter.remaining();
+    let parser_input = to_parser_input(edition, buffer);
     let tree_traversal = entry_point.parse(&parser_input, edition);
-    let mut cursor = buffer.begin();
+    let mut cursor = buffer.cursor();
     let mut error = false;
     for step in tree_traversal.iter() {
         match step {
@@ -378,13 +380,13 @@ pub fn expect_fragment(
                     n_input_tokens = 2;
                 }
                 for _ in 0..n_input_tokens {
-                    cursor = cursor.bump_subtree();
+                    cursor.bump_or_end();
                 }
             }
             parser::Step::FloatSplit { .. } => {
                 // FIXME: We need to split the tree properly here, but mutating the token trees
                 // in the buffer is somewhat tricky to pull off.
-                cursor = cursor.bump_subtree();
+                cursor.bump_or_end();
             }
             parser::Step::Enter { .. } | parser::Step::Exit => (),
             parser::Step::Error { .. } => error = true,
@@ -393,29 +395,19 @@ pub fn expect_fragment(
 
     let err = if error || !cursor.is_root() {
         Some(ExpandError::binding_error(
-            buffer.begin().token_tree().map_or(delim_span.close, |tt| tt.span()),
+            buffer.cursor().token_tree().map_or(delim_span.close, |tt| tt.first_span()),
             format!("expected {entry_point:?}"),
         ))
     } else {
         None
     };
 
-    let mut curr = buffer.begin();
-    let mut res = vec![];
-
-    while curr != cursor {
-        let Some(token) = curr.token_tree() else { break };
-        res.push(token.cloned());
-        curr = curr.bump();
+    while !cursor.is_root() {
+        cursor.bump_or_end();
     }
 
-    *tt_iter = TtIter::new_iter(tt_iter.as_slice()[res.len()..].iter());
-    let res = match &*res {
-        [] | [_] => res.pop(),
-        [first, ..] => Some(tt::TokenTree::Subtree(tt::Subtree {
-            delimiter: Delimiter::invisible_spanned(first.first_span()),
-            token_trees: res.into_boxed_slice(),
-        })),
-    };
+    let res = cursor.crossed();
+    tt_iter.flat_advance(res.len());
+
     ExpandResult { value: res, err }
 }
diff --git a/src/tools/rust-analyzer/crates/mbe/src/parser.rs b/src/tools/rust-analyzer/crates/mbe/src/parser.rs
index b55edf4a5e0..16d55492a04 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/parser.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/parser.rs
@@ -6,7 +6,7 @@ use std::sync::Arc;
 use arrayvec::ArrayVec;
 use intern::{sym, Symbol};
 use span::{Edition, Span, SyntaxContextId};
-use tt::iter::TtIter;
+use tt::iter::{TtElement, TtIter};
 
 use crate::ParseError;
 
@@ -29,14 +29,14 @@ pub(crate) struct MetaTemplate(pub(crate) Box<[Op]>);
 impl MetaTemplate {
     pub(crate) fn parse_pattern(
         edition: impl Copy + Fn(SyntaxContextId) -> Edition,
-        pattern: &tt::Subtree<Span>,
+        pattern: TtIter<'_, Span>,
     ) -> Result<Self, ParseError> {
         MetaTemplate::parse(edition, pattern, Mode::Pattern)
     }
 
     pub(crate) fn parse_template(
         edition: impl Copy + Fn(SyntaxContextId) -> Edition,
-        template: &tt::Subtree<Span>,
+        template: TtIter<'_, Span>,
     ) -> Result<Self, ParseError> {
         MetaTemplate::parse(edition, template, Mode::Template)
     }
@@ -47,13 +47,11 @@ impl MetaTemplate {
 
     fn parse(
         edition: impl Copy + Fn(SyntaxContextId) -> Edition,
-        tt: &tt::Subtree<Span>,
+        mut src: TtIter<'_, Span>,
         mode: Mode,
     ) -> Result<Self, ParseError> {
-        let mut src = TtIter::new(tt);
-
         let mut res = Vec::new();
-        while let Some(first) = src.peek_n(0) {
+        while let Some(first) = src.peek() {
             let op = next_op(edition, first, &mut src, mode)?;
             res.push(op);
         }
@@ -182,12 +180,12 @@ enum Mode {
 
 fn next_op(
     edition: impl Copy + Fn(SyntaxContextId) -> Edition,
-    first_peeked: &tt::TokenTree<Span>,
+    first_peeked: TtElement<'_, Span>,
     src: &mut TtIter<'_, Span>,
     mode: Mode,
 ) -> Result<Op, ParseError> {
     let res = match first_peeked {
-        tt::TokenTree::Leaf(tt::Leaf::Punct(p @ tt::Punct { char: '$', .. })) => {
+        TtElement::Leaf(tt::Leaf::Punct(p @ tt::Punct { char: '$', .. })) => {
             src.next().expect("first token already peeked");
             // Note that the '$' itself is a valid token inside macro_rules.
             let second = match src.next() {
@@ -201,18 +199,16 @@ fn next_op(
                 Some(it) => it,
             };
             match second {
-                tt::TokenTree::Subtree(subtree) => match subtree.delimiter.kind {
+                TtElement::Subtree(subtree, mut subtree_iter) => match subtree.delimiter.kind {
                     tt::DelimiterKind::Parenthesis => {
                         let (separator, kind) = parse_repeat(src)?;
-                        let tokens = MetaTemplate::parse(edition, subtree, mode)?;
+                        let tokens = MetaTemplate::parse(edition, subtree_iter, mode)?;
                         Op::Repeat { tokens, separator: separator.map(Arc::new), kind }
                     }
                     tt::DelimiterKind::Brace => match mode {
-                        Mode::Template => {
-                            parse_metavar_expr(&mut TtIter::new(subtree)).map_err(|()| {
-                                ParseError::unexpected("invalid metavariable expression")
-                            })?
-                        }
+                        Mode::Template => parse_metavar_expr(&mut subtree_iter).map_err(|()| {
+                            ParseError::unexpected("invalid metavariable expression")
+                        })?,
                         Mode::Pattern => {
                             return Err(ParseError::unexpected(
                                 "`${}` metavariable expressions are not allowed in matchers",
@@ -225,7 +221,7 @@ fn next_op(
                         ))
                     }
                 },
-                tt::TokenTree::Leaf(leaf) => match leaf {
+                TtElement::Leaf(leaf) => match leaf {
                     tt::Leaf::Ident(ident) if ident.sym == sym::crate_ => {
                         // We simply produce identifier `$crate` here. And it will be resolved when lowering ast to Path.
                         Op::Ident(tt::Ident {
@@ -265,25 +261,25 @@ fn next_op(
             }
         }
 
-        tt::TokenTree::Leaf(tt::Leaf::Literal(it)) => {
+        TtElement::Leaf(tt::Leaf::Literal(it)) => {
             src.next().expect("first token already peeked");
             Op::Literal(it.clone())
         }
 
-        tt::TokenTree::Leaf(tt::Leaf::Ident(it)) => {
+        TtElement::Leaf(tt::Leaf::Ident(it)) => {
             src.next().expect("first token already peeked");
             Op::Ident(it.clone())
         }
 
-        tt::TokenTree::Leaf(tt::Leaf::Punct(_)) => {
+        TtElement::Leaf(tt::Leaf::Punct(_)) => {
             // There's at least one punct so this shouldn't fail.
             let puncts = src.expect_glued_punct().unwrap();
             Op::Punct(Box::new(puncts))
         }
 
-        tt::TokenTree::Subtree(subtree) => {
+        TtElement::Subtree(subtree, subtree_iter) => {
             src.next().expect("first token already peeked");
-            let tokens = MetaTemplate::parse(edition, subtree, mode)?;
+            let tokens = MetaTemplate::parse(edition, subtree_iter, mode)?;
             Op::Subtree { tokens, delimiter: subtree.delimiter }
         }
     };
@@ -343,8 +339,8 @@ fn parse_repeat(src: &mut TtIter<'_, Span>) -> Result<(Option<Separator>, Repeat
     let mut separator = Separator::Puncts(ArrayVec::new());
     for tt in src {
         let tt = match tt {
-            tt::TokenTree::Leaf(leaf) => leaf,
-            tt::TokenTree::Subtree(_) => return Err(ParseError::InvalidRepeat),
+            TtElement::Leaf(leaf) => leaf,
+            TtElement::Subtree(..) => return Err(ParseError::InvalidRepeat),
         };
         let has_sep = match &separator {
             Separator::Puncts(puncts) => !puncts.is_empty(),
@@ -378,37 +374,39 @@ fn parse_repeat(src: &mut TtIter<'_, Span>) -> Result<(Option<Separator>, Repeat
 
 fn parse_metavar_expr(src: &mut TtIter<'_, Span>) -> Result<Op, ()> {
     let func = src.expect_ident()?;
-    let args = src.expect_subtree()?;
+    let (args, mut args_iter) = src.expect_subtree()?;
 
     if args.delimiter.kind != tt::DelimiterKind::Parenthesis {
         return Err(());
     }
 
-    let mut args = TtIter::new(args);
-
     let op = match &func.sym {
         s if sym::ignore == *s => {
-            args.expect_dollar()?;
-            let ident = args.expect_ident()?;
+            args_iter.expect_dollar()?;
+            let ident = args_iter.expect_ident()?;
             Op::Ignore { name: ident.sym.clone(), id: ident.span }
         }
-        s if sym::index == *s => Op::Index { depth: parse_depth(&mut args)? },
-        s if sym::len == *s => Op::Len { depth: parse_depth(&mut args)? },
+        s if sym::index == *s => Op::Index { depth: parse_depth(&mut args_iter)? },
+        s if sym::len == *s => Op::Len { depth: parse_depth(&mut args_iter)? },
         s if sym::count == *s => {
-            args.expect_dollar()?;
-            let ident = args.expect_ident()?;
-            let depth = if try_eat_comma(&mut args) { Some(parse_depth(&mut args)?) } else { None };
+            args_iter.expect_dollar()?;
+            let ident = args_iter.expect_ident()?;
+            let depth = if try_eat_comma(&mut args_iter) {
+                Some(parse_depth(&mut args_iter)?)
+            } else {
+                None
+            };
             Op::Count { name: ident.sym.clone(), depth }
         }
         s if sym::concat == *s => {
             let mut elements = Vec::new();
-            while let Some(next) = args.peek_n(0) {
-                let element = if let tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) = next {
-                    args.next().expect("already peeked");
+            while let Some(next) = args_iter.peek() {
+                let element = if let TtElement::Leaf(tt::Leaf::Literal(lit)) = next {
+                    args_iter.next().expect("already peeked");
                     ConcatMetaVarExprElem::Literal(lit.clone())
                 } else {
-                    let is_var = try_eat_dollar(&mut args);
-                    let ident = args.expect_ident_or_underscore()?.clone();
+                    let is_var = try_eat_dollar(&mut args_iter);
+                    let ident = args_iter.expect_ident_or_underscore()?.clone();
 
                     if is_var {
                         ConcatMetaVarExprElem::Var(ident)
@@ -417,8 +415,8 @@ fn parse_metavar_expr(src: &mut TtIter<'_, Span>) -> Result<Op, ()> {
                     }
                 };
                 elements.push(element);
-                if args.peek_n(0).is_some() {
-                    args.expect_comma()?;
+                if !args_iter.is_empty() {
+                    args_iter.expect_comma()?;
                 }
             }
             if elements.len() < 2 {
@@ -429,7 +427,7 @@ fn parse_metavar_expr(src: &mut TtIter<'_, Span>) -> Result<Op, ()> {
         _ => return Err(()),
     };
 
-    if args.next().is_some() {
+    if args_iter.next().is_some() {
         return Err(());
     }
 
@@ -437,7 +435,7 @@ fn parse_metavar_expr(src: &mut TtIter<'_, Span>) -> Result<Op, ()> {
 }
 
 fn parse_depth(src: &mut TtIter<'_, Span>) -> Result<usize, ()> {
-    if src.len() == 0 {
+    if src.is_empty() {
         Ok(0)
     } else if let tt::Leaf::Literal(tt::Literal { symbol: text, suffix: None, .. }) =
         src.expect_literal()?
@@ -450,7 +448,7 @@ fn parse_depth(src: &mut TtIter<'_, Span>) -> Result<usize, ()> {
 }
 
 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) {
+    if let Some(TtElement::Leaf(tt::Leaf::Punct(tt::Punct { char: ',', .. }))) = src.peek() {
         let _ = src.next();
         return true;
     }
@@ -458,7 +456,7 @@ fn try_eat_comma(src: &mut TtIter<'_, Span>) -> bool {
 }
 
 fn try_eat_dollar(src: &mut TtIter<'_, Span>) -> bool {
-    if let Some(tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: '$', .. }))) = src.peek_n(0) {
+    if let Some(TtElement::Leaf(tt::Leaf::Punct(tt::Punct { char: '$', .. }))) = src.peek() {
         let _ = src.next();
         return true;
     }
diff --git a/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge/tests.rs b/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge/tests.rs
deleted file mode 100644
index 2988fb3cf15..00000000000
--- a/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge/tests.rs
+++ /dev/null
@@ -1,101 +0,0 @@
-use rustc_hash::FxHashMap;
-use span::Span;
-use syntax::{ast, AstNode};
-use test_utils::extract_annotations;
-use tt::{
-    buffer::{TokenBuffer, TokenTreeRef},
-    Leaf, Punct, Spacing,
-};
-
-use crate::{syntax_node_to_token_tree, DocCommentDesugarMode, DummyTestSpanMap, DUMMY};
-
-fn check_punct_spacing(fixture: &str) {
-    let source_file = ast::SourceFile::parse(fixture, span::Edition::CURRENT).ok().unwrap();
-    let subtree = syntax_node_to_token_tree(
-        source_file.syntax(),
-        DummyTestSpanMap,
-        DUMMY,
-        DocCommentDesugarMode::Mbe,
-    );
-    let mut annotations: FxHashMap<_, _> = extract_annotations(fixture)
-        .into_iter()
-        .map(|(range, annotation)| {
-            let spacing = match annotation.as_str() {
-                "Alone" => Spacing::Alone,
-                "Joint" => Spacing::Joint,
-                a => panic!("unknown annotation: {a}"),
-            };
-            (range, spacing)
-        })
-        .collect();
-
-    let buf = TokenBuffer::from_subtree(&subtree);
-    let mut cursor = buf.begin();
-    while !cursor.eof() {
-        while let Some(token_tree) = cursor.token_tree() {
-            if let TokenTreeRef::Leaf(
-                Leaf::Punct(Punct { spacing, span: Span { range, .. }, .. }),
-                _,
-            ) = token_tree
-            {
-                if let Some(expected) = annotations.remove(range) {
-                    assert_eq!(expected, *spacing);
-                }
-            }
-            cursor = cursor.bump_subtree();
-        }
-        cursor = cursor.bump();
-    }
-
-    assert!(annotations.is_empty(), "unchecked annotations: {annotations:?}");
-}
-
-#[test]
-fn punct_spacing() {
-    check_punct_spacing(
-        r#"
-fn main() {
-    0+0;
-   //^ Alone
-    0+(0);
-   //^ Alone
-    0<=0;
-   //^ Joint
-   // ^ Alone
-    0<=(0);
-   // ^ Alone
-    a=0;
-   //^ Alone
-    a=(0);
-   //^ Alone
-    a+=0;
-   //^ Joint
-   // ^ Alone
-    a+=(0);
-   // ^ Alone
-    a&&b;
-   //^ Joint
-   // ^ Alone
-    a&&(b);
-   // ^ Alone
-    foo::bar;
-   //  ^ Joint
-   //   ^ Alone
-    use foo::{bar,baz,};
-   //       ^ Alone
-   //            ^ Alone
-   //                ^ Alone
-    struct Struct<'a> {};
-   //            ^ Joint
-   //             ^ Joint
-    Struct::<0>;
-   //       ^ Alone
-    Struct::<{0}>;
-   //       ^ Alone
-    ;;
-  //^ Joint
-  // ^ Alone
-}
-        "#,
-    );
-}
diff --git a/src/tools/rust-analyzer/crates/parser/src/input.rs b/src/tools/rust-analyzer/crates/parser/src/input.rs
index 9504bd4d9ec..c90b358cfbb 100644
--- a/src/tools/rust-analyzer/crates/parser/src/input.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/input.rs
@@ -72,7 +72,7 @@ impl Input {
     }
     pub(crate) fn is_joint(&self, n: usize) -> bool {
         let (idx, b_idx) = self.bit_index(n);
-        self.joint[idx] & 1 << b_idx != 0
+        self.joint[idx] & (1 << b_idx) != 0
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/parser/src/output.rs b/src/tools/rust-analyzer/crates/parser/src/output.rs
index 41d4c68b2d7..386d03a62cc 100644
--- a/src/tools/rust-analyzer/crates/parser/src/output.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/output.rs
@@ -85,7 +85,7 @@ impl Output {
     }
 
     pub(crate) fn float_split_hack(&mut self, ends_in_dot: bool) {
-        let e = (Self::SPLIT_EVENT as u32) << Self::TAG_SHIFT
+        let e = ((Self::SPLIT_EVENT as u32) << Self::TAG_SHIFT)
             | ((ends_in_dot as u32) << Self::N_INPUT_TOKEN_SHIFT)
             | Self::EVENT_MASK;
         self.event.push(e);
@@ -99,7 +99,7 @@ impl Output {
     }
 
     pub(crate) fn leave_node(&mut self) {
-        let e = (Self::EXIT_EVENT as u32) << Self::TAG_SHIFT | Self::EVENT_MASK;
+        let e = ((Self::EXIT_EVENT as u32) << Self::TAG_SHIFT) | Self::EVENT_MASK;
         self.event.push(e)
     }
 
diff --git a/src/tools/rust-analyzer/crates/parser/src/shortcuts.rs b/src/tools/rust-analyzer/crates/parser/src/shortcuts.rs
index 7adedba7c43..32569d5c3fe 100644
--- a/src/tools/rust-analyzer/crates/parser/src/shortcuts.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/shortcuts.rs
@@ -5,7 +5,7 @@
 //! abstract token parsing, and string tokenization as completely separate
 //! layers.
 //!
-//! However, often you do pares text into syntax trees and the glue code for
+//! However, often you do parse text into syntax trees and the glue code for
 //! that needs to live somewhere. Rather than putting it to lexer or parser, we
 //! use a separate shortcuts module for that.
 
diff --git a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs
index 0c9c6ffd715..318f71a2d4d 100644
--- a/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs
@@ -331,6 +331,331 @@ pub enum SyntaxKind {
 }
 use self::SyntaxKind::*;
 impl SyntaxKind {
+    #[allow(unreachable_patterns)]
+    pub const fn text(self) -> &'static str {
+        match self {
+            TOMBSTONE
+            | EOF
+            | __LAST
+            | BYTE
+            | BYTE_STRING
+            | CHAR
+            | C_STRING
+            | FLOAT_NUMBER
+            | INT_NUMBER
+            | RAW_BYTE_STRING
+            | RAW_C_STRING
+            | RAW_STRING
+            | STRING
+            | ABI
+            | ADT
+            | ARG_LIST
+            | ARRAY_EXPR
+            | ARRAY_TYPE
+            | ASM_CLOBBER_ABI
+            | ASM_CONST
+            | ASM_DIR_SPEC
+            | ASM_EXPR
+            | ASM_LABEL
+            | ASM_OPERAND
+            | ASM_OPERAND_EXPR
+            | ASM_OPERAND_NAMED
+            | ASM_OPTION
+            | ASM_OPTIONS
+            | ASM_PIECE
+            | ASM_REG_OPERAND
+            | ASM_REG_SPEC
+            | ASM_SYM
+            | ASSOC_ITEM
+            | ASSOC_ITEM_LIST
+            | ASSOC_TYPE_ARG
+            | ATTR
+            | AWAIT_EXPR
+            | BECOME_EXPR
+            | BIN_EXPR
+            | BLOCK_EXPR
+            | BOX_PAT
+            | BREAK_EXPR
+            | CALL_EXPR
+            | CAST_EXPR
+            | CLOSURE_BINDER
+            | CLOSURE_EXPR
+            | CONST
+            | CONST_ARG
+            | CONST_BLOCK_PAT
+            | CONST_PARAM
+            | CONTINUE_EXPR
+            | DYN_TRAIT_TYPE
+            | ENUM
+            | EXPR
+            | EXPR_STMT
+            | EXTERN_BLOCK
+            | EXTERN_CRATE
+            | EXTERN_ITEM
+            | EXTERN_ITEM_LIST
+            | FIELD_EXPR
+            | FIELD_LIST
+            | FN
+            | FN_PTR_TYPE
+            | FORMAT_ARGS_ARG
+            | FORMAT_ARGS_EXPR
+            | FOR_EXPR
+            | FOR_TYPE
+            | GENERIC_ARG
+            | GENERIC_ARG_LIST
+            | GENERIC_PARAM
+            | GENERIC_PARAM_LIST
+            | IDENT_PAT
+            | IF_EXPR
+            | IMPL
+            | IMPL_TRAIT_TYPE
+            | INDEX_EXPR
+            | INFER_TYPE
+            | ITEM
+            | ITEM_LIST
+            | LABEL
+            | LET_ELSE
+            | LET_EXPR
+            | LET_STMT
+            | LIFETIME
+            | LIFETIME_ARG
+            | LIFETIME_PARAM
+            | LITERAL
+            | LITERAL_PAT
+            | LOOP_EXPR
+            | MACRO_CALL
+            | MACRO_DEF
+            | MACRO_EXPR
+            | MACRO_ITEMS
+            | MACRO_PAT
+            | MACRO_RULES
+            | MACRO_STMTS
+            | MACRO_TYPE
+            | MATCH_ARM
+            | MATCH_ARM_LIST
+            | MATCH_EXPR
+            | MATCH_GUARD
+            | META
+            | METHOD_CALL_EXPR
+            | MODULE
+            | NAME
+            | NAME_REF
+            | NEVER_TYPE
+            | OFFSET_OF_EXPR
+            | OR_PAT
+            | PARAM
+            | PARAM_LIST
+            | PARENTHESIZED_ARG_LIST
+            | PAREN_EXPR
+            | PAREN_PAT
+            | PAREN_TYPE
+            | PAT
+            | PATH
+            | PATH_EXPR
+            | PATH_PAT
+            | PATH_SEGMENT
+            | PATH_TYPE
+            | PREFIX_EXPR
+            | PTR_TYPE
+            | RANGE_EXPR
+            | RANGE_PAT
+            | RECORD_EXPR
+            | RECORD_EXPR_FIELD
+            | RECORD_EXPR_FIELD_LIST
+            | RECORD_FIELD
+            | RECORD_FIELD_LIST
+            | RECORD_PAT
+            | RECORD_PAT_FIELD
+            | RECORD_PAT_FIELD_LIST
+            | REF_EXPR
+            | REF_PAT
+            | REF_TYPE
+            | RENAME
+            | REST_PAT
+            | RETURN_EXPR
+            | RETURN_TYPE_SYNTAX
+            | RET_TYPE
+            | SELF_PARAM
+            | SLICE_PAT
+            | SLICE_TYPE
+            | SOURCE_FILE
+            | STATIC
+            | STMT
+            | STMT_LIST
+            | STRUCT
+            | TOKEN_TREE
+            | TRAIT
+            | TRAIT_ALIAS
+            | TRY_EXPR
+            | TUPLE_EXPR
+            | TUPLE_FIELD
+            | TUPLE_FIELD_LIST
+            | TUPLE_PAT
+            | TUPLE_STRUCT_PAT
+            | TUPLE_TYPE
+            | TYPE
+            | TYPE_ALIAS
+            | TYPE_ARG
+            | TYPE_BOUND
+            | TYPE_BOUND_LIST
+            | TYPE_PARAM
+            | UNDERSCORE_EXPR
+            | UNION
+            | USE
+            | USE_BOUND_GENERIC_ARG
+            | USE_BOUND_GENERIC_ARGS
+            | USE_TREE
+            | USE_TREE_LIST
+            | VARIANT
+            | VARIANT_LIST
+            | VISIBILITY
+            | WHERE_CLAUSE
+            | WHERE_PRED
+            | WHILE_EXPR
+            | WILDCARD_PAT
+            | YEET_EXPR
+            | YIELD_EXPR
+            | COMMENT
+            | ERROR
+            | IDENT
+            | LIFETIME_IDENT
+            | NEWLINE
+            | SHEBANG
+            | WHITESPACE => panic!("no text for these `SyntaxKind`s"),
+            DOLLAR => "$",
+            SEMICOLON => ";",
+            COMMA => ",",
+            L_PAREN => "(",
+            R_PAREN => ")",
+            L_CURLY => "{",
+            R_CURLY => "}",
+            L_BRACK => "[",
+            R_BRACK => "]",
+            L_ANGLE => "<",
+            R_ANGLE => ">",
+            AT => "@",
+            POUND => "#",
+            TILDE => "~",
+            QUESTION => "?",
+            AMP => "&",
+            PIPE => "|",
+            PLUS => "+",
+            STAR => "*",
+            SLASH => "/",
+            CARET => "^",
+            PERCENT => "%",
+            UNDERSCORE => "_",
+            DOT => ".",
+            DOT2 => "..",
+            DOT3 => "...",
+            DOT2EQ => "..=",
+            COLON => ":",
+            COLON2 => "::",
+            EQ => "=",
+            EQ2 => "==",
+            FAT_ARROW => "=>",
+            BANG => "!",
+            NEQ => "!=",
+            MINUS => "-",
+            THIN_ARROW => "->",
+            LTEQ => "<=",
+            GTEQ => ">=",
+            PLUSEQ => "+=",
+            MINUSEQ => "-=",
+            PIPEEQ => "|=",
+            AMPEQ => "&=",
+            CARETEQ => "^=",
+            SLASHEQ => "/=",
+            STAREQ => "*=",
+            PERCENTEQ => "%=",
+            AMP2 => "&&",
+            PIPE2 => "||",
+            SHL => "<<",
+            SHR => ">>",
+            SHLEQ => "<<=",
+            SHREQ => ">>=",
+            SELF_TYPE_KW => "Self",
+            ABSTRACT_KW => "abstract",
+            AS_KW => "as",
+            BECOME_KW => "become",
+            BOX_KW => "box",
+            BREAK_KW => "break",
+            CONST_KW => "const",
+            CONTINUE_KW => "continue",
+            CRATE_KW => "crate",
+            DO_KW => "do",
+            ELSE_KW => "else",
+            ENUM_KW => "enum",
+            EXTERN_KW => "extern",
+            FALSE_KW => "false",
+            FINAL_KW => "final",
+            FN_KW => "fn",
+            FOR_KW => "for",
+            IF_KW => "if",
+            IMPL_KW => "impl",
+            IN_KW => "in",
+            LET_KW => "let",
+            LOOP_KW => "loop",
+            MACRO_KW => "macro",
+            MATCH_KW => "match",
+            MOD_KW => "mod",
+            MOVE_KW => "move",
+            MUT_KW => "mut",
+            OVERRIDE_KW => "override",
+            PRIV_KW => "priv",
+            PUB_KW => "pub",
+            REF_KW => "ref",
+            RETURN_KW => "return",
+            SELF_KW => "self",
+            STATIC_KW => "static",
+            STRUCT_KW => "struct",
+            SUPER_KW => "super",
+            TRAIT_KW => "trait",
+            TRUE_KW => "true",
+            TYPE_KW => "type",
+            TYPEOF_KW => "typeof",
+            UNSAFE_KW => "unsafe",
+            UNSIZED_KW => "unsized",
+            USE_KW => "use",
+            VIRTUAL_KW => "virtual",
+            WHERE_KW => "where",
+            WHILE_KW => "while",
+            YIELD_KW => "yield",
+            ASM_KW => "asm",
+            ATT_SYNTAX_KW => "att_syntax",
+            AUTO_KW => "auto",
+            BUILTIN_KW => "builtin",
+            CLOBBER_ABI_KW => "clobber_abi",
+            DEFAULT_KW => "default",
+            DYN_KW => "dyn",
+            FORMAT_ARGS_KW => "format_args",
+            INLATEOUT_KW => "inlateout",
+            INOUT_KW => "inout",
+            LABEL_KW => "label",
+            LATEOUT_KW => "lateout",
+            MACRO_RULES_KW => "macro_rules",
+            MAY_UNWIND_KW => "may_unwind",
+            NOMEM_KW => "nomem",
+            NORETURN_KW => "noreturn",
+            NOSTACK_KW => "nostack",
+            OFFSET_OF_KW => "offset_of",
+            OPTIONS_KW => "options",
+            OUT_KW => "out",
+            PRESERVES_FLAGS_KW => "preserves_flags",
+            PURE_KW => "pure",
+            RAW_KW => "raw",
+            READONLY_KW => "readonly",
+            SAFE_KW => "safe",
+            SYM_KW => "sym",
+            UNION_KW => "union",
+            YEET_KW => "yeet",
+            ASYNC_KW => "async",
+            AWAIT_KW => "await",
+            DYN_KW => "dyn",
+            GEN_KW => "gen",
+            TRY_KW => "try",
+        }
+    }
     #[doc = r" Checks whether this syntax kind is a strict keyword for the given edition."]
     #[doc = r" Strict keywords are identifiers that are always considered keywords."]
     pub fn is_strict_keyword(self, edition: Edition) -> bool {
diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/json.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/json.rs
index ec89f6a9e65..ec89f6a9e65 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-api/src/json.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/json.rs
diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs
index bbd9f582df9..6ea8db9a905 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg.rs
@@ -9,10 +9,10 @@ use serde_derive::{Deserialize, Serialize};
 
 use crate::ProcMacroKind;
 
-pub use crate::msg::flat::{
+pub use self::flat::{
     deserialize_span_data_index_map, serialize_span_data_index_map, FlatTree, SpanDataIndexMap,
-    TokenId,
 };
+pub use span::TokenId;
 
 // The versions of the server protocol
 pub const NO_VERSION_CHECK_VERSION: u32 = 0;
@@ -160,11 +160,14 @@ type ProtocolWrite<W: Write> = for<'o, 'msg> fn(out: &'o mut W, msg: &'msg str)
 mod tests {
     use intern::{sym, Symbol};
     use span::{ErasedFileAstId, Span, SpanAnchor, SyntaxContextId, TextRange, TextSize};
-    use tt::{Delimiter, DelimiterKind, Ident, Leaf, Literal, Punct, Spacing, Subtree, TokenTree};
+    use tt::{
+        Delimiter, DelimiterKind, Ident, Leaf, Literal, Punct, Spacing, TopSubtree,
+        TopSubtreeBuilder,
+    };
 
     use super::*;
 
-    fn fixture_token_tree() -> Subtree<Span> {
+    fn fixture_token_tree() -> TopSubtree<Span> {
         let anchor = SpanAnchor {
             file_id: span::EditionedFileId::new(
                 span::FileId::from_raw(0xe4e4e),
@@ -173,93 +176,88 @@ mod tests {
             ast_id: ErasedFileAstId::from_raw(0),
         };
 
-        let token_trees = Box::new([
-            TokenTree::Leaf(
-                Ident {
-                    sym: Symbol::intern("struct"),
-                    span: Span {
-                        range: TextRange::at(TextSize::new(0), TextSize::of("struct")),
-                        anchor,
-                        ctx: SyntaxContextId::ROOT,
-                    },
-                    is_raw: tt::IdentIsRaw::No,
-                }
-                .into(),
-            ),
-            TokenTree::Leaf(
-                Ident {
-                    sym: Symbol::intern("Foo"),
-                    span: Span {
-                        range: TextRange::at(TextSize::new(5), TextSize::of("r#Foo")),
-                        anchor,
-                        ctx: SyntaxContextId::ROOT,
-                    },
-                    is_raw: tt::IdentIsRaw::Yes,
-                }
-                .into(),
-            ),
-            TokenTree::Leaf(Leaf::Literal(Literal {
-                symbol: Symbol::intern("Foo"),
+        let mut builder = TopSubtreeBuilder::new(Delimiter {
+            open: Span {
+                range: TextRange::empty(TextSize::new(0)),
+                anchor,
+                ctx: SyntaxContextId::ROOT,
+            },
+            close: Span {
+                range: TextRange::empty(TextSize::new(19)),
+                anchor,
+                ctx: SyntaxContextId::ROOT,
+            },
+            kind: DelimiterKind::Invisible,
+        });
+
+        builder.push(
+            Ident {
+                sym: Symbol::intern("struct"),
                 span: Span {
-                    range: TextRange::at(TextSize::new(10), TextSize::of("\"Foo\"")),
+                    range: TextRange::at(TextSize::new(0), TextSize::of("struct")),
                     anchor,
                     ctx: SyntaxContextId::ROOT,
                 },
-                kind: tt::LitKind::Str,
-                suffix: None,
-            })),
-            TokenTree::Leaf(Leaf::Punct(Punct {
-                char: '@',
+                is_raw: tt::IdentIsRaw::No,
+            }
+            .into(),
+        );
+        builder.push(
+            Ident {
+                sym: Symbol::intern("Foo"),
                 span: Span {
-                    range: TextRange::at(TextSize::new(13), TextSize::of('@')),
+                    range: TextRange::at(TextSize::new(5), TextSize::of("r#Foo")),
                     anchor,
                     ctx: SyntaxContextId::ROOT,
                 },
-                spacing: Spacing::Joint,
-            })),
-            TokenTree::Subtree(Subtree {
-                delimiter: Delimiter {
-                    open: Span {
-                        range: TextRange::at(TextSize::new(14), TextSize::of('{')),
-                        anchor,
-                        ctx: SyntaxContextId::ROOT,
-                    },
-                    close: Span {
-                        range: TextRange::at(TextSize::new(19), TextSize::of('}')),
-                        anchor,
-                        ctx: SyntaxContextId::ROOT,
-                    },
-                    kind: DelimiterKind::Brace,
-                },
-                token_trees: Box::new([TokenTree::Leaf(Leaf::Literal(Literal {
-                    symbol: sym::INTEGER_0.clone(),
-                    span: Span {
-                        range: TextRange::at(TextSize::new(15), TextSize::of("0u32")),
-                        anchor,
-                        ctx: SyntaxContextId::ROOT,
-                    },
-                    kind: tt::LitKind::Integer,
-                    suffix: Some(sym::u32.clone()),
-                }))]),
-            }),
-        ]);
-
-        Subtree {
-            delimiter: Delimiter {
-                open: Span {
-                    range: TextRange::empty(TextSize::new(0)),
-                    anchor,
-                    ctx: SyntaxContextId::ROOT,
-                },
-                close: Span {
-                    range: TextRange::empty(TextSize::new(19)),
-                    anchor,
-                    ctx: SyntaxContextId::ROOT,
-                },
-                kind: DelimiterKind::Invisible,
+                is_raw: tt::IdentIsRaw::Yes,
+            }
+            .into(),
+        );
+        builder.push(Leaf::Literal(Literal {
+            symbol: Symbol::intern("Foo"),
+            span: Span {
+                range: TextRange::at(TextSize::new(10), TextSize::of("\"Foo\"")),
+                anchor,
+                ctx: SyntaxContextId::ROOT,
             },
-            token_trees,
-        }
+            kind: tt::LitKind::Str,
+            suffix: None,
+        }));
+        builder.push(Leaf::Punct(Punct {
+            char: '@',
+            span: Span {
+                range: TextRange::at(TextSize::new(13), TextSize::of('@')),
+                anchor,
+                ctx: SyntaxContextId::ROOT,
+            },
+            spacing: Spacing::Joint,
+        }));
+        builder.open(
+            DelimiterKind::Brace,
+            Span {
+                range: TextRange::at(TextSize::new(14), TextSize::of('{')),
+                anchor,
+                ctx: SyntaxContextId::ROOT,
+            },
+        );
+        builder.push(Leaf::Literal(Literal {
+            symbol: sym::INTEGER_0.clone(),
+            span: Span {
+                range: TextRange::at(TextSize::new(15), TextSize::of("0u32")),
+                anchor,
+                ctx: SyntaxContextId::ROOT,
+            },
+            kind: tt::LitKind::Integer,
+            suffix: Some(sym::u32.clone()),
+        }));
+        builder.close(Span {
+            range: TextRange::at(TextSize::new(19), TextSize::of('}')),
+            anchor,
+            ctx: SyntaxContextId::ROOT,
+        });
+
+        builder.build()
     }
 
     #[test]
@@ -269,7 +267,7 @@ mod tests {
             let mut span_data_table = Default::default();
             let task = ExpandMacro {
                 data: ExpandMacroData {
-                    macro_body: FlatTree::new(&tt, v, &mut span_data_table),
+                    macro_body: FlatTree::new(tt.view(), v, &mut span_data_table),
                     macro_name: Default::default(),
                     attributes: None,
                     has_global_spans: ExpnGlobals {
@@ -289,9 +287,8 @@ mod tests {
             // println!("{}", json);
             let back: ExpandMacro = serde_json::from_str(&json).unwrap();
 
-            assert_eq!(
-                tt,
-                back.data.macro_body.to_subtree_resolved(v, &span_data_table),
+            assert!(
+                tt == back.data.macro_body.to_subtree_resolved(v, &span_data_table),
                 "version: {v}"
             );
         }
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/legacy_protocol/msg/flat.rs
index ce4b060fca5..c194f301714 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-api/src/msg/flat.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg/flat.rs
@@ -1,13 +1,13 @@
-//! Serialization-friendly representation of `tt::Subtree`.
+//! Serialization-friendly representation of `tt::TopSubtree`.
 //!
-//! It is possible to serialize `Subtree` as is, as a tree, but using
+//! It is possible to serialize `TopSubtree` recursively, as a tree, but using
 //! arbitrary-nested trees in JSON is problematic, as they can cause the JSON
 //! parser to overflow the stack.
 //!
 //! Additionally, such implementation would be pretty verbose, and we do care
 //! about performance here a bit.
 //!
-//! So what this module does is dumping a `tt::Subtree` into a bunch of flat
+//! So what this module does is dumping a `tt::TopSubtree` into a bunch of flat
 //! array of numbers. See the test in the parent module to get an example
 //! output.
 //!
@@ -40,9 +40,11 @@ use std::collections::VecDeque;
 use intern::Symbol;
 use rustc_hash::FxHashMap;
 use serde_derive::{Deserialize, Serialize};
-use span::{EditionedFileId, ErasedFileAstId, Span, SpanAnchor, SyntaxContextId, TextRange};
+use span::{
+    EditionedFileId, ErasedFileAstId, Span, SpanAnchor, SyntaxContextId, TextRange, TokenId,
+};
 
-use crate::msg::{ENCODE_CLOSE_SPAN_VERSION, EXTENDED_LEAF_DATA};
+use crate::legacy_protocol::msg::{ENCODE_CLOSE_SPAN_VERSION, EXTENDED_LEAF_DATA};
 
 pub type SpanDataIndexMap =
     indexmap::IndexSet<Span, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>;
@@ -78,15 +80,6 @@ pub fn deserialize_span_data_index_map(map: &[u32]) -> SpanDataIndexMap {
         .collect()
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Hash)]
-pub struct TokenId(pub u32);
-
-impl std::fmt::Debug for TokenId {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        self.0.fmt(f)
-    }
-}
-
 #[derive(Serialize, Deserialize, Debug)]
 pub struct FlatTree {
     subtree: Vec<u32>,
@@ -125,7 +118,7 @@ struct IdentRepr {
 
 impl FlatTree {
     pub fn new(
-        subtree: &tt::Subtree<Span>,
+        subtree: tt::SubtreeView<'_, Span>,
         version: u32,
         span_data_table: &mut SpanDataIndexMap,
     ) -> FlatTree {
@@ -166,7 +159,7 @@ impl FlatTree {
         }
     }
 
-    pub fn new_raw(subtree: &tt::Subtree<TokenId>, version: u32) -> FlatTree {
+    pub fn new_raw(subtree: tt::SubtreeView<'_, TokenId>, version: u32) -> FlatTree {
         let mut w = Writer {
             string_table: FxHashMap::default(),
             work: VecDeque::new(),
@@ -208,7 +201,7 @@ impl FlatTree {
         self,
         version: u32,
         span_data_table: &SpanDataIndexMap,
-    ) -> tt::Subtree<Span> {
+    ) -> tt::TopSubtree<Span> {
         Reader {
             subtree: if version >= ENCODE_CLOSE_SPAN_VERSION {
                 read_vec(self.subtree, SubtreeRepr::read_with_close_span)
@@ -234,7 +227,7 @@ impl FlatTree {
         .read()
     }
 
-    pub fn to_subtree_unresolved(self, version: u32) -> tt::Subtree<TokenId> {
+    pub fn to_subtree_unresolved(self, version: u32) -> tt::TopSubtree<TokenId> {
         Reader {
             subtree: if version >= ENCODE_CLOSE_SPAN_VERSION {
                 read_vec(self.subtree, SubtreeRepr::read_with_close_span)
@@ -388,7 +381,7 @@ impl InternableSpan for Span {
 }
 
 struct Writer<'a, 'span, S: InternableSpan> {
-    work: VecDeque<(usize, &'a tt::Subtree<S>)>,
+    work: VecDeque<(usize, tt::iter::TtIter<'a, S>)>,
     string_table: FxHashMap<std::borrow::Cow<'a, str>, u32>,
     span_data_table: &'span mut S::Table,
     version: u32,
@@ -402,8 +395,9 @@ struct Writer<'a, 'span, S: InternableSpan> {
 }
 
 impl<'a, S: InternableSpan> Writer<'a, '_, S> {
-    fn write(&mut self, root: &'a tt::Subtree<S>) {
-        self.enqueue(root);
+    fn write(&mut self, root: tt::SubtreeView<'a, S>) {
+        let subtree = root.top_subtree();
+        self.enqueue(subtree, root.iter());
         while let Some((idx, subtree)) = self.work.pop_front() {
             self.subtree(idx, subtree);
         }
@@ -413,20 +407,20 @@ impl<'a, S: InternableSpan> Writer<'a, '_, S> {
         S::token_id_of(self.span_data_table, span)
     }
 
-    fn subtree(&mut self, idx: usize, subtree: &'a tt::Subtree<S>) {
+    fn subtree(&mut self, idx: usize, subtree: tt::iter::TtIter<'a, S>) {
         let mut first_tt = self.token_tree.len();
-        let n_tt = subtree.token_trees.len();
+        let n_tt = subtree.clone().count(); // FIXME: `count()` walks over the entire iterator.
         self.token_tree.resize(first_tt + n_tt, !0);
 
         self.subtree[idx].tt = [first_tt as u32, (first_tt + n_tt) as u32];
 
-        for child in subtree.token_trees.iter() {
+        for child in subtree {
             let idx_tag = match child {
-                tt::TokenTree::Subtree(it) => {
-                    let idx = self.enqueue(it);
+                tt::iter::TtElement::Subtree(subtree, subtree_iter) => {
+                    let idx = self.enqueue(subtree, subtree_iter);
                     idx << 2
                 }
-                tt::TokenTree::Leaf(leaf) => match leaf {
+                tt::iter::TtElement::Leaf(leaf) => match leaf {
                     tt::Leaf::Literal(lit) => {
                         let idx = self.literal.len() as u32;
                         let id = self.token_id_of(lit.span);
@@ -456,13 +450,13 @@ impl<'a, S: InternableSpan> Writer<'a, '_, S> {
                             }),
                             suffix,
                         });
-                        idx << 2 | 0b01
+                        (idx << 2) | 0b01
                     }
                     tt::Leaf::Punct(punct) => {
                         let idx = self.punct.len() as u32;
                         let id = self.token_id_of(punct.span);
                         self.punct.push(PunctRepr { char: punct.char, spacing: punct.spacing, id });
-                        idx << 2 | 0b10
+                        (idx << 2) | 0b10
                     }
                     tt::Leaf::Ident(ident) => {
                         let idx = self.ident.len() as u32;
@@ -475,7 +469,7 @@ impl<'a, S: InternableSpan> Writer<'a, '_, S> {
                             self.intern(ident.sym.as_str())
                         };
                         self.ident.push(IdentRepr { id, text, is_raw: ident.is_raw.yes() });
-                        idx << 2 | 0b11
+                        (idx << 2) | 0b11
                     }
                 },
             };
@@ -484,13 +478,13 @@ impl<'a, S: InternableSpan> Writer<'a, '_, S> {
         }
     }
 
-    fn enqueue(&mut self, subtree: &'a tt::Subtree<S>) -> u32 {
+    fn enqueue(&mut self, subtree: &'a tt::Subtree<S>, contents: tt::iter::TtIter<'a, S>) -> u32 {
         let idx = self.subtree.len();
         let open = self.token_id_of(subtree.delimiter.open);
         let close = self.token_id_of(subtree.delimiter.close);
         let delimiter_kind = subtree.delimiter.kind;
         self.subtree.push(SubtreeRepr { open, close, kind: delimiter_kind, tt: [!0, !0] });
-        self.work.push_back((idx, subtree));
+        self.work.push_back((idx, contents));
         idx as u32
     }
 
@@ -525,103 +519,110 @@ struct Reader<'span, S: InternableSpan> {
 }
 
 impl<S: InternableSpan> Reader<'_, S> {
-    pub(crate) fn read(self) -> tt::Subtree<S> {
-        let mut res: Vec<Option<tt::Subtree<S>>> = vec![None; self.subtree.len()];
+    pub(crate) fn read(self) -> tt::TopSubtree<S> {
+        let mut res: Vec<Option<(tt::Delimiter<S>, Vec<tt::TokenTree<S>>)>> =
+            vec![None; self.subtree.len()];
         let read_span = |id| S::span_for_token_id(self.span_data_table, id);
         for i in (0..self.subtree.len()).rev() {
             let repr = &self.subtree[i];
             let token_trees = &self.token_tree[repr.tt[0] as usize..repr.tt[1] as usize];
-            let s = tt::Subtree {
-                delimiter: tt::Delimiter {
-                    open: read_span(repr.open),
-                    close: read_span(repr.close),
-                    kind: repr.kind,
-                },
-                token_trees: token_trees
-                    .iter()
-                    .copied()
-                    .map(|idx_tag| {
-                        let tag = idx_tag & 0b11;
-                        let idx = (idx_tag >> 2) as usize;
-                        match tag {
-                            // XXX: we iterate subtrees in reverse to guarantee
-                            // that this unwrap doesn't fire.
-                            0b00 => res[idx].take().unwrap().into(),
-                            0b01 => {
-                                use tt::LitKind::*;
-                                let repr = &self.literal[idx];
-                                let text = self.text[repr.text as usize].as_str();
-                                let span = read_span(repr.id);
-                                tt::Leaf::Literal(if self.version >= EXTENDED_LEAF_DATA {
-                                    tt::Literal {
-                                        symbol: Symbol::intern(text),
-                                        span,
-                                        kind: match u16::to_le_bytes(repr.kind) {
-                                            [0, _] => Err(()),
-                                            [1, _] => Byte,
-                                            [2, _] => Char,
-                                            [3, _] => Integer,
-                                            [4, _] => Float,
-                                            [5, _] => Str,
-                                            [6, r] => StrRaw(r),
-                                            [7, _] => ByteStr,
-                                            [8, r] => ByteStrRaw(r),
-                                            [9, _] => CStr,
-                                            [10, r] => CStrRaw(r),
-                                            _ => unreachable!(),
-                                        },
-                                        suffix: if repr.suffix != !0 {
-                                            Some(Symbol::intern(
-                                                self.text[repr.suffix as usize].as_str(),
-                                            ))
-                                        } else {
-                                            None
-                                        },
-                                    }
-                                } else {
-                                    tt::token_to_literal(text, span)
-                                })
-                                .into()
-                            }
-                            0b10 => {
-                                let repr = &self.punct[idx];
-                                tt::Leaf::Punct(tt::Punct {
-                                    char: repr.char,
-                                    spacing: repr.spacing,
-                                    span: read_span(repr.id),
-                                })
-                                .into()
-                            }
-                            0b11 => {
-                                let repr = &self.ident[idx];
-                                let text = self.text[repr.text as usize].as_str();
-                                let (is_raw, text) = if self.version >= EXTENDED_LEAF_DATA {
-                                    (
-                                        if repr.is_raw {
-                                            tt::IdentIsRaw::Yes
-                                        } else {
-                                            tt::IdentIsRaw::No
-                                        },
-                                        text,
-                                    )
-                                } else {
-                                    tt::IdentIsRaw::split_from_symbol(text)
-                                };
-                                tt::Leaf::Ident(tt::Ident {
-                                    sym: Symbol::intern(text),
-                                    span: read_span(repr.id),
-                                    is_raw,
-                                })
-                                .into()
-                            }
-                            other => panic!("bad tag: {other}"),
-                        }
-                    })
-                    .collect(),
+            let delimiter = tt::Delimiter {
+                open: read_span(repr.open),
+                close: read_span(repr.close),
+                kind: repr.kind,
             };
-            res[i] = Some(s);
+            let mut s = Vec::new();
+            for &idx_tag in token_trees {
+                let tag = idx_tag & 0b11;
+                let idx = (idx_tag >> 2) as usize;
+                match tag {
+                    // XXX: we iterate subtrees in reverse to guarantee
+                    // that this unwrap doesn't fire.
+                    0b00 => {
+                        let (delimiter, subtree) = res[idx].take().unwrap();
+                        s.push(tt::TokenTree::Subtree(tt::Subtree {
+                            delimiter,
+                            len: subtree.len() as u32,
+                        }));
+                        s.extend(subtree)
+                    }
+                    0b01 => {
+                        use tt::LitKind::*;
+                        let repr = &self.literal[idx];
+                        let text = self.text[repr.text as usize].as_str();
+                        let span = read_span(repr.id);
+                        s.push(
+                            tt::Leaf::Literal(if self.version >= EXTENDED_LEAF_DATA {
+                                tt::Literal {
+                                    symbol: Symbol::intern(text),
+                                    span,
+                                    kind: match u16::to_le_bytes(repr.kind) {
+                                        [0, _] => Err(()),
+                                        [1, _] => Byte,
+                                        [2, _] => Char,
+                                        [3, _] => Integer,
+                                        [4, _] => Float,
+                                        [5, _] => Str,
+                                        [6, r] => StrRaw(r),
+                                        [7, _] => ByteStr,
+                                        [8, r] => ByteStrRaw(r),
+                                        [9, _] => CStr,
+                                        [10, r] => CStrRaw(r),
+                                        _ => unreachable!(),
+                                    },
+                                    suffix: if repr.suffix != !0 {
+                                        Some(Symbol::intern(
+                                            self.text[repr.suffix as usize].as_str(),
+                                        ))
+                                    } else {
+                                        None
+                                    },
+                                }
+                            } else {
+                                tt::token_to_literal(text, span)
+                            })
+                            .into(),
+                        )
+                    }
+                    0b10 => {
+                        let repr = &self.punct[idx];
+                        s.push(
+                            tt::Leaf::Punct(tt::Punct {
+                                char: repr.char,
+                                spacing: repr.spacing,
+                                span: read_span(repr.id),
+                            })
+                            .into(),
+                        )
+                    }
+                    0b11 => {
+                        let repr = &self.ident[idx];
+                        let text = self.text[repr.text as usize].as_str();
+                        let (is_raw, text) = if self.version >= EXTENDED_LEAF_DATA {
+                            (
+                                if repr.is_raw { tt::IdentIsRaw::Yes } else { tt::IdentIsRaw::No },
+                                text,
+                            )
+                        } else {
+                            tt::IdentIsRaw::split_from_symbol(text)
+                        };
+                        s.push(
+                            tt::Leaf::Ident(tt::Ident {
+                                sym: Symbol::intern(text),
+                                span: read_span(repr.id),
+                                is_raw,
+                            })
+                            .into(),
+                        )
+                    }
+                    other => panic!("bad tag: {other}"),
+                }
+            }
+            res[i] = Some((delimiter, s));
         }
 
-        res[0].take().unwrap()
+        let (delimiter, mut res) = res[0].take().unwrap();
+        res.insert(0, tt::TokenTree::Subtree(tt::Subtree { delimiter, len: res.len() as u32 }));
+        tt::TopSubtree(res.into_boxed_slice())
     }
 }
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 e54d501b94c..dc3328ebcda 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
@@ -5,26 +5,26 @@
 //! is used to provide basic infrastructure for communication between two
 //! processes: Client (RA itself), Server (the external program)
 
-pub mod json;
-pub mod msg;
+pub mod legacy_protocol {
+    pub mod json;
+    pub mod msg;
+}
 mod process;
 
 use paths::{AbsPath, AbsPathBuf};
 use span::Span;
 use std::{fmt, io, sync::Arc};
 
-use serde::{Deserialize, Serialize};
-
 use crate::{
-    msg::{
+    legacy_protocol::msg::{
         deserialize_span_data_index_map, flat::serialize_span_data_index_map, ExpandMacro,
-        ExpnGlobals, FlatTree, PanicMessage, SpanDataIndexMap, HAS_GLOBAL_SPANS,
-        RUST_ANALYZER_SPAN_SUPPORT,
+        ExpandMacroData, ExpnGlobals, FlatTree, PanicMessage, Request, Response, SpanDataIndexMap,
+        HAS_GLOBAL_SPANS, RUST_ANALYZER_SPAN_SUPPORT,
     },
-    process::ProcMacroProcessSrv,
+    process::ProcMacroServerProcess,
 };
 
-#[derive(Copy, Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
+#[derive(Copy, Clone, Eq, PartialEq, Debug, serde_derive::Serialize, serde_derive::Deserialize)]
 pub enum ProcMacroKind {
     CustomDerive,
     Attr,
@@ -37,12 +37,12 @@ pub enum ProcMacroKind {
 /// A handle to an external process which load dylibs with macros (.so or .dll)
 /// and runs actual macro expansion functions.
 #[derive(Debug)]
-pub struct ProcMacroServer {
+pub struct ProcMacroClient {
     /// Currently, the proc macro process expands all procedural macros sequentially.
     ///
     /// That means that concurrent salsa requests may block each other when expanding proc macros,
     /// which is unfortunate, but simple and good enough for the time being.
-    process: Arc<ProcMacroProcessSrv>,
+    process: Arc<ProcMacroServerProcess>,
     path: AbsPathBuf,
 }
 
@@ -56,13 +56,13 @@ impl MacroDylib {
     }
 }
 
-/// A handle to a specific macro (a `#[proc_macro]` annotated function).
+/// A handle to a specific proc-macro (a `#[proc_macro]` annotated function).
 ///
-/// It exists within a context of a specific [`ProcMacroProcess`] -- currently
-/// we share a single expander process for all macros.
+/// It exists within the context of a specific proc-macro server -- currently
+/// we share a single expander process for all macros within a workspace.
 #[derive(Debug, Clone)]
 pub struct ProcMacro {
-    process: Arc<ProcMacroProcessSrv>,
+    process: Arc<ProcMacroServerProcess>,
     dylib_path: Arc<AbsPathBuf>,
     name: Box<str>,
     kind: ProcMacroKind,
@@ -95,21 +95,22 @@ impl fmt::Display for ServerError {
     }
 }
 
-impl ProcMacroServer {
+impl ProcMacroClient {
     /// Spawns an external process as the proc macro server and returns a client connected to it.
     pub fn spawn(
         process_path: &AbsPath,
         env: impl IntoIterator<Item = (impl AsRef<std::ffi::OsStr>, impl AsRef<std::ffi::OsStr>)>
             + Clone,
-    ) -> io::Result<ProcMacroServer> {
-        let process = ProcMacroProcessSrv::run(process_path, env)?;
-        Ok(ProcMacroServer { process: Arc::new(process), path: process_path.to_owned() })
+    ) -> io::Result<ProcMacroClient> {
+        let process = ProcMacroServerProcess::run(process_path, env)?;
+        Ok(ProcMacroClient { process: Arc::new(process), path: process_path.to_owned() })
     }
 
-    pub fn path(&self) -> &AbsPath {
+    pub fn server_path(&self) -> &AbsPath {
         &self.path
     }
 
+    /// Loads a proc-macro dylib into the server process returning a list of `ProcMacro`s loaded.
     pub fn load_dylib(&self, dylib: MacroDylib) -> Result<Vec<ProcMacro>, ServerError> {
         let _p = tracing::info_span!("ProcMacroServer::load_dylib").entered();
         let macros = self.process.find_proc_macros(&dylib.path)?;
@@ -145,14 +146,14 @@ impl ProcMacro {
 
     pub fn expand(
         &self,
-        subtree: &tt::Subtree<Span>,
-        attr: Option<&tt::Subtree<Span>>,
+        subtree: tt::SubtreeView<'_, Span>,
+        attr: Option<tt::SubtreeView<'_, Span>>,
         env: Vec<(String, String)>,
         def_site: Span,
         call_site: Span,
         mixed_site: Span,
         current_dir: Option<String>,
-    ) -> Result<Result<tt::Subtree<Span>, PanicMessage>, ServerError> {
+    ) -> Result<Result<tt::TopSubtree<Span>, PanicMessage>, ServerError> {
         let version = self.process.version();
 
         let mut span_data_table = SpanDataIndexMap::default();
@@ -160,7 +161,7 @@ impl ProcMacro {
         let call_site = span_data_table.insert_full(call_site).0;
         let mixed_site = span_data_table.insert_full(mixed_site).0;
         let task = ExpandMacro {
-            data: msg::ExpandMacroData {
+            data: ExpandMacroData {
                 macro_body: FlatTree::new(subtree, version, &mut span_data_table),
                 macro_name: self.name.to_string(),
                 attributes: attr
@@ -182,13 +183,13 @@ impl ProcMacro {
             current_dir,
         };
 
-        let response = self.process.send_task(msg::Request::ExpandMacro(Box::new(task)))?;
+        let response = self.process.send_task(Request::ExpandMacro(Box::new(task)))?;
 
         match response {
-            msg::Response::ExpandMacro(it) => {
+            Response::ExpandMacro(it) => {
                 Ok(it.map(|tree| FlatTree::to_subtree_resolved(tree, version, &span_data_table)))
             }
-            msg::Response::ExpandMacroExtended(it) => Ok(it.map(|resp| {
+            Response::ExpandMacroExtended(it) => Ok(it.map(|resp| {
                 FlatTree::to_subtree_resolved(
                     resp.tree,
                     version,
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 4045e25fdf1..d998b23d3bb 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
@@ -11,13 +11,18 @@ use paths::AbsPath;
 use stdx::JodChild;
 
 use crate::{
-    json::{read_json, write_json},
-    msg::{Message, Request, Response, SpanMode, CURRENT_API_VERSION, RUST_ANALYZER_SPAN_SUPPORT},
+    legacy_protocol::{
+        json::{read_json, write_json},
+        msg::{
+            Message, Request, Response, ServerConfig, SpanMode, CURRENT_API_VERSION,
+            RUST_ANALYZER_SPAN_SUPPORT,
+        },
+    },
     ProcMacroKind, ServerError,
 };
 
 #[derive(Debug)]
-pub(crate) struct ProcMacroProcessSrv {
+pub(crate) struct ProcMacroServerProcess {
     /// The state of the proc-macro server process, the protocol is currently strictly sequential
     /// hence the lock on the state.
     state: Mutex<ProcessSrvState>,
@@ -34,24 +39,24 @@ struct ProcessSrvState {
     stdout: BufReader<ChildStdout>,
 }
 
-impl ProcMacroProcessSrv {
+impl ProcMacroServerProcess {
     pub(crate) fn run(
         process_path: &AbsPath,
         env: impl IntoIterator<Item = (impl AsRef<std::ffi::OsStr>, impl AsRef<std::ffi::OsStr>)>
             + Clone,
-    ) -> io::Result<ProcMacroProcessSrv> {
-        let create_srv = |null_stderr| {
-            let mut process = Process::run(process_path, env.clone(), null_stderr)?;
+    ) -> io::Result<ProcMacroServerProcess> {
+        let create_srv = || {
+            let mut process = Process::run(process_path, env.clone())?;
             let (stdin, stdout) = process.stdio().expect("couldn't access child stdio");
 
-            io::Result::Ok(ProcMacroProcessSrv {
+            io::Result::Ok(ProcMacroServerProcess {
                 state: Mutex::new(ProcessSrvState { process, stdin, stdout }),
                 version: 0,
                 mode: SpanMode::Id,
                 exited: OnceLock::new(),
             })
         };
-        let mut srv = create_srv(true)?;
+        let mut srv = create_srv()?;
         tracing::info!("sending proc-macro server version check");
         match srv.version_check() {
             Ok(v) if v > CURRENT_API_VERSION => Err(io::Error::new(
@@ -62,7 +67,6 @@ impl ProcMacroProcessSrv {
             )),
             Ok(v) => {
                 tracing::info!("Proc-macro server version: {v}");
-                srv = create_srv(false)?;
                 srv.version = v;
                 if srv.version >= RUST_ANALYZER_SPAN_SUPPORT {
                     if let Ok(mode) = srv.enable_rust_analyzer_spans() {
@@ -73,8 +77,10 @@ impl ProcMacroProcessSrv {
                 Ok(srv)
             }
             Err(e) => {
-                tracing::info!(%e, "proc-macro version check failed, restarting and assuming version 0");
-                create_srv(false)
+                tracing::info!(%e, "proc-macro version check failed");
+                Err(
+                    io::Error::new(io::ErrorKind::Other, format!("proc-macro server version check failed: {e}")),
+                )
             }
         }
     }
@@ -98,13 +104,11 @@ impl ProcMacroProcessSrv {
     }
 
     fn enable_rust_analyzer_spans(&self) -> Result<SpanMode, ServerError> {
-        let request = Request::SetConfig(crate::msg::ServerConfig {
-            span_mode: crate::msg::SpanMode::RustAnalyzer,
-        });
+        let request = Request::SetConfig(ServerConfig { span_mode: SpanMode::RustAnalyzer });
         let response = self.send_task(request)?;
 
         match response {
-            Response::SetConfig(crate::msg::ServerConfig { span_mode }) => Ok(span_mode),
+            Response::SetConfig(ServerConfig { span_mode }) => Ok(span_mode),
             _ => Err(ServerError { message: "unexpected response".to_owned(), io: None }),
         }
     }
@@ -182,9 +186,8 @@ impl Process {
     fn run(
         path: &AbsPath,
         env: impl IntoIterator<Item = (impl AsRef<std::ffi::OsStr>, impl AsRef<std::ffi::OsStr>)>,
-        null_stderr: bool,
     ) -> io::Result<Process> {
-        let child = JodChild(mk_child(path, env, null_stderr)?);
+        let child = JodChild(mk_child(path, env)?);
         Ok(Process { child })
     }
 
@@ -200,14 +203,14 @@ impl Process {
 fn mk_child(
     path: &AbsPath,
     env: impl IntoIterator<Item = (impl AsRef<std::ffi::OsStr>, impl AsRef<std::ffi::OsStr>)>,
-    null_stderr: bool,
 ) -> io::Result<Child> {
+    #[allow(clippy::disallowed_methods)]
     let mut cmd = Command::new(path);
     cmd.envs(env)
         .env("RUST_ANALYZER_INTERNALS_DO_NOT_USE", "this is unstable")
         .stdin(Stdio::piped())
         .stdout(Stdio::piped())
-        .stderr(if null_stderr { Stdio::null() } else { Stdio::inherit() });
+        .stderr(Stdio::inherit());
     if cfg!(windows) {
         let mut path_var = std::ffi::OsString::new();
         path_var.push(path.parent().unwrap().parent().unwrap());
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/Cargo.toml
index 1c394513c45..57a28b00365 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/Cargo.toml
@@ -12,6 +12,7 @@ rust-version.workspace = true
 [dependencies]
 proc-macro-srv.workspace = true
 proc-macro-api.workspace = true
+tt.workspace = true
 
 [features]
 sysroot-abi = ["proc-macro-srv/sysroot-abi"]
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs
index 137efd5e7a0..de59e88aac4 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main.rs
@@ -6,7 +6,10 @@
 #[cfg(feature = "in-rust-tree")]
 extern crate rustc_driver as _;
 
-use std::io;
+#[cfg(any(feature = "sysroot-abi", rust_analyzer))]
+mod main_loop;
+#[cfg(any(feature = "sysroot-abi", rust_analyzer))]
+use main_loop::run;
 
 fn main() -> std::io::Result<()> {
     let v = std::env::var("RUST_ANALYZER_INTERNALS_DO_NOT_USE");
@@ -22,57 +25,10 @@ fn main() -> std::io::Result<()> {
 }
 
 #[cfg(not(any(feature = "sysroot-abi", rust_analyzer)))]
-fn run() -> io::Result<()> {
-    Err(io::Error::new(
-        io::ErrorKind::Unsupported,
+fn run() -> std::io::Result<()> {
+    Err(std::io::Error::new(
+        std::io::ErrorKind::Unsupported,
         "proc-macro-srv-cli needs to be compiled with the `sysroot-abi` feature to function"
             .to_owned(),
     ))
 }
-
-#[cfg(any(feature = "sysroot-abi", rust_analyzer))]
-fn run() -> io::Result<()> {
-    use proc_macro_api::{
-        json::{read_json, write_json},
-        msg::{self, Message},
-    };
-    use proc_macro_srv::EnvSnapshot;
-
-    let read_request =
-        |buf: &mut String| msg::Request::read(read_json, &mut io::stdin().lock(), buf);
-
-    let write_response = |msg: msg::Response| msg.write(write_json, &mut io::stdout().lock());
-
-    let env = EnvSnapshot::default();
-    let mut srv = proc_macro_srv::ProcMacroSrv::new(&env);
-    let mut buf = String::new();
-
-    while let Some(req) = read_request(&mut buf)? {
-        let res = match req {
-            msg::Request::ListMacros { dylib_path } => {
-                msg::Response::ListMacros(srv.list_macros(&dylib_path))
-            }
-            msg::Request::ExpandMacro(task) => match srv.span_mode() {
-                msg::SpanMode::Id => {
-                    msg::Response::ExpandMacro(srv.expand(*task).map(|(it, _)| it))
-                }
-                msg::SpanMode::RustAnalyzer => msg::Response::ExpandMacroExtended(
-                    srv.expand(*task).map(|(tree, span_data_table)| msg::ExpandMacroExtended {
-                        tree,
-                        span_data_table,
-                    }),
-                ),
-            },
-            msg::Request::ApiVersionCheck {} => {
-                msg::Response::ApiVersionCheck(proc_macro_api::msg::CURRENT_API_VERSION)
-            }
-            msg::Request::SetConfig(config) => {
-                srv.set_span_mode(config.span_mode);
-                msg::Response::SetConfig(config)
-            }
-        };
-        write_response(res)?
-    }
-
-    Ok(())
-}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main_loop.rs b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main_loop.rs
new file mode 100644
index 00000000000..ba1fcd8e336
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main_loop.rs
@@ -0,0 +1,134 @@
+//! The main loop of the proc-macro server.
+use std::io;
+
+use proc_macro_api::legacy_protocol::{
+    json::{read_json, write_json},
+    msg::{
+        self, deserialize_span_data_index_map, serialize_span_data_index_map, ExpandMacroData,
+        ExpnGlobals, Message, SpanMode, TokenId, CURRENT_API_VERSION,
+    },
+};
+use proc_macro_srv::EnvSnapshot;
+
+pub(crate) fn run() -> io::Result<()> {
+    fn macro_kind_to_api(kind: proc_macro_srv::ProcMacroKind) -> proc_macro_api::ProcMacroKind {
+        match kind {
+            proc_macro_srv::ProcMacroKind::CustomDerive => {
+                proc_macro_api::ProcMacroKind::CustomDerive
+            }
+            proc_macro_srv::ProcMacroKind::Bang => proc_macro_api::ProcMacroKind::Bang,
+            proc_macro_srv::ProcMacroKind::Attr => proc_macro_api::ProcMacroKind::Attr,
+        }
+    }
+
+    let read_request =
+        |buf: &mut String| msg::Request::read(read_json, &mut io::stdin().lock(), buf);
+
+    let write_response = |msg: msg::Response| msg.write(write_json, &mut io::stdout().lock());
+
+    let env = EnvSnapshot::default();
+    let mut srv = proc_macro_srv::ProcMacroSrv::new(&env);
+    let mut buf = String::new();
+
+    let mut span_mode = SpanMode::Id;
+
+    while let Some(req) = read_request(&mut buf)? {
+        let res = match req {
+            msg::Request::ListMacros { dylib_path } => {
+                msg::Response::ListMacros(srv.list_macros(&dylib_path).map(|macros| {
+                    macros.into_iter().map(|(name, kind)| (name, macro_kind_to_api(kind))).collect()
+                }))
+            }
+            msg::Request::ExpandMacro(task) => {
+                let msg::ExpandMacro {
+                    lib,
+                    env,
+                    current_dir,
+                    data:
+                        ExpandMacroData {
+                            macro_body,
+                            macro_name,
+                            attributes,
+                            has_global_spans:
+                                ExpnGlobals { serialize: _, def_site, call_site, mixed_site },
+                            span_data_table,
+                        },
+                } = *task;
+                match span_mode {
+                    SpanMode::Id => msg::Response::ExpandMacro({
+                        let def_site = TokenId(def_site as u32);
+                        let call_site = TokenId(call_site as u32);
+                        let mixed_site = TokenId(mixed_site as u32);
+
+                        let macro_body = macro_body.to_subtree_unresolved(CURRENT_API_VERSION);
+                        let attributes =
+                            attributes.map(|it| it.to_subtree_unresolved(CURRENT_API_VERSION));
+
+                        srv.expand(
+                            lib,
+                            env,
+                            current_dir,
+                            macro_name,
+                            macro_body,
+                            attributes,
+                            def_site,
+                            call_site,
+                            mixed_site,
+                        )
+                        .map(|it| {
+                            msg::FlatTree::new_raw(tt::SubtreeView::new(&it), CURRENT_API_VERSION)
+                        })
+                        .map_err(msg::PanicMessage)
+                    }),
+                    SpanMode::RustAnalyzer => msg::Response::ExpandMacroExtended({
+                        let mut span_data_table = deserialize_span_data_index_map(&span_data_table);
+
+                        let def_site = span_data_table[def_site];
+                        let call_site = span_data_table[call_site];
+                        let mixed_site = span_data_table[mixed_site];
+
+                        let macro_body =
+                            macro_body.to_subtree_resolved(CURRENT_API_VERSION, &span_data_table);
+                        let attributes = attributes.map(|it| {
+                            it.to_subtree_resolved(CURRENT_API_VERSION, &span_data_table)
+                        });
+                        srv.expand(
+                            lib,
+                            env,
+                            current_dir,
+                            macro_name,
+                            macro_body,
+                            attributes,
+                            def_site,
+                            call_site,
+                            mixed_site,
+                        )
+                        .map(|it| {
+                            (
+                                msg::FlatTree::new(
+                                    tt::SubtreeView::new(&it),
+                                    CURRENT_API_VERSION,
+                                    &mut span_data_table,
+                                ),
+                                serialize_span_data_index_map(&span_data_table),
+                            )
+                        })
+                        .map(|(tree, span_data_table)| msg::ExpandMacroExtended {
+                            tree,
+                            span_data_table,
+                        })
+                        .map_err(msg::PanicMessage)
+                    }),
+                }
+            }
+            msg::Request::ApiVersionCheck {} => msg::Response::ApiVersionCheck(CURRENT_API_VERSION),
+            msg::Request::SetConfig(config) => {
+                span_mode = config.span_mode;
+                msg::Response::SetConfig(config)
+            }
+        };
+        write_response(res)?
+    }
+
+    Ok(())
+}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml
index 98385969459..00695c54737 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml
@@ -23,7 +23,6 @@ syntax-bridge.workspace = true
 paths.workspace = true
 # span = {workspace = true, default-features = false} does not work
 span = { path = "../span", version = "0.0.0", default-features = false}
-proc-macro-api.workspace = true
 intern.workspace = true
 
 ra-ap-rustc_lexer.workspace = true
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/build.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/build.rs
index 9a17cfc9f36..07a10aaae57 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/build.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/build.rs
@@ -7,6 +7,7 @@ fn main() {
     println!("cargo::rustc-check-cfg=cfg(rust_analyzer)");
 
     let rustc = env::var("RUSTC").expect("proc-macro-srv's build script expects RUSTC to be set");
+    #[allow(clippy::disallowed_methods)]
     let output = Command::new(rustc).arg("--version").output().expect("rustc --version must run");
     let version_string = std::str::from_utf8(&output.stdout[..])
         .expect("rustc --version output must be UTF-8")
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs
index ff2f5d18639..d3d58a6df01 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs
@@ -7,6 +7,8 @@
 //! a specific rustup toolchain: this allows testing against older ABIs (e.g.
 //! 1.58) and future ABIs (stage1, nightly)
 
+#![allow(clippy::disallowed_methods)]
+
 use std::{
     env,
     path::{Path, PathBuf},
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 26f6af84aae..fe15d42b4e4 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
@@ -8,39 +8,8 @@ use std::{fmt, fs, io, time::SystemTime};
 use libloading::Library;
 use object::Object;
 use paths::{Utf8Path, Utf8PathBuf};
-use proc_macro_api::ProcMacroKind;
 
-use crate::ProcMacroSrvSpan;
-
-const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_";
-
-fn invalid_data_err(e: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> io::Error {
-    io::Error::new(io::ErrorKind::InvalidData, e)
-}
-
-fn is_derive_registrar_symbol(symbol: &str) -> bool {
-    symbol.contains(NEW_REGISTRAR_SYMBOL)
-}
-
-fn find_registrar_symbol(obj: &object::File<'_>) -> object::Result<Option<String>> {
-    Ok(obj
-        .exports()?
-        .into_iter()
-        .map(|export| export.name())
-        .filter_map(|sym| String::from_utf8(sym.into()).ok())
-        .find(|sym| is_derive_registrar_symbol(sym))
-        .map(|sym| {
-            // From MacOS docs:
-            // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlsym.3.html
-            // Unlike other dyld API's, the symbol name passed to dlsym() must NOT be
-            // prepended with an underscore.
-            if cfg!(target_os = "macos") && sym.starts_with('_') {
-                sym[1..].to_owned()
-            } else {
-                sym
-            }
-        }))
-}
+use crate::{proc_macros::ProcMacros, server_impl::TopSubtree, ProcMacroKind, ProcMacroSrvSpan};
 
 /// Loads dynamic library in platform dependent manner.
 ///
@@ -100,13 +69,14 @@ impl From<libloading::Error> for LoadProcMacroDylibError {
     }
 }
 
-struct ProcMacroLibraryLibloading {
+struct ProcMacroLibrary {
+    // 'static is actually the lifetime of library, so make sure this drops before _lib
+    proc_macros: &'static ProcMacros,
     // Hold on to the library so it doesn't unload
     _lib: Library,
-    proc_macros: crate::proc_macros::ProcMacros,
 }
 
-impl ProcMacroLibraryLibloading {
+impl ProcMacroLibrary {
     fn open(path: &Utf8Path) -> Result<Self, LoadProcMacroDylibError> {
         let file = fs::File::open(path)?;
         let file = unsafe { memmap2::Mmap::map(&file) }?;
@@ -119,27 +89,22 @@ impl ProcMacroLibraryLibloading {
             })?;
 
         let lib = load_library(path).map_err(invalid_data_err)?;
-        let proc_macros = crate::proc_macros::ProcMacros::from_lib(
-            &lib,
-            symbol_name,
-            &version_info.version_string,
-        )?;
-        Ok(ProcMacroLibraryLibloading { _lib: lib, proc_macros })
-    }
-}
-
-struct RemoveFileOnDrop(Utf8PathBuf);
-impl Drop for RemoveFileOnDrop {
-    fn drop(&mut self) {
-        #[cfg(windows)]
-        std::fs::remove_file(&self.0).unwrap();
-        _ = self.0;
+        let proc_macros = unsafe {
+            // SAFETY: We extend the lifetime here to avoid referential borrow problems
+            // We never reveal proc_macros to the outside and drop it before _lib
+            std::mem::transmute::<&ProcMacros, &'static ProcMacros>(ProcMacros::from_lib(
+                &lib,
+                symbol_name,
+                &version_info.version_string,
+            )?)
+        };
+        Ok(ProcMacroLibrary { _lib: lib, proc_macros })
     }
 }
 
 // Drop order matters as we can't remove the dylib before the library is unloaded
 pub(crate) struct Expander {
-    inner: ProcMacroLibraryLibloading,
+    inner: ProcMacroLibrary,
     _remove_on_drop: RemoveFileOnDrop,
     modified_time: SystemTime,
 }
@@ -152,7 +117,7 @@ impl Expander {
         let modified_time = fs::metadata(&lib).and_then(|it| it.modified())?;
 
         let path = ensure_file_with_lock_free_access(&lib)?;
-        let library = ProcMacroLibraryLibloading::open(path.as_ref())?;
+        let library = ProcMacroLibrary::open(path.as_ref())?;
 
         Ok(Expander { inner: library, _remove_on_drop: RemoveFileOnDrop(path), modified_time })
     }
@@ -160,12 +125,12 @@ impl Expander {
     pub(crate) fn expand<S: ProcMacroSrvSpan>(
         &self,
         macro_name: &str,
-        macro_body: tt::Subtree<S>,
-        attributes: Option<tt::Subtree<S>>,
+        macro_body: TopSubtree<S>,
+        attributes: Option<TopSubtree<S>>,
         def_site: S,
         call_site: S,
         mixed_site: S,
-    ) -> Result<tt::Subtree<S>, String>
+    ) -> Result<TopSubtree<S>, String>
     where
         <S::Server as bridge::server::Types>::TokenStream: Default,
     {
@@ -185,6 +150,44 @@ impl Expander {
     }
 }
 
+fn invalid_data_err(e: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> io::Error {
+    io::Error::new(io::ErrorKind::InvalidData, e)
+}
+
+fn is_derive_registrar_symbol(symbol: &str) -> bool {
+    const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_";
+    symbol.contains(NEW_REGISTRAR_SYMBOL)
+}
+
+fn find_registrar_symbol(obj: &object::File<'_>) -> object::Result<Option<String>> {
+    Ok(obj
+        .exports()?
+        .into_iter()
+        .map(|export| export.name())
+        .filter_map(|sym| String::from_utf8(sym.into()).ok())
+        .find(|sym| is_derive_registrar_symbol(sym))
+        .map(|sym| {
+            // From MacOS docs:
+            // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlsym.3.html
+            // Unlike other dyld API's, the symbol name passed to dlsym() must NOT be
+            // prepended with an underscore.
+            if cfg!(target_os = "macos") && sym.starts_with('_') {
+                sym[1..].to_owned()
+            } else {
+                sym
+            }
+        }))
+}
+
+struct RemoveFileOnDrop(Utf8PathBuf);
+impl Drop for RemoveFileOnDrop {
+    fn drop(&mut self) {
+        #[cfg(windows)]
+        std::fs::remove_file(&self.0).unwrap();
+        _ = self.0;
+    }
+}
+
 /// Copy the dylib to temp directory to prevent locking in Windows
 #[cfg(windows)]
 fn ensure_file_with_lock_free_access(path: &Utf8Path) -> io::Result<Utf8PathBuf> {
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 85833dab1b0..7ae75713ebf 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
@@ -14,6 +14,7 @@
 #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
 #![feature(proc_macro_internals, proc_macro_diagnostic, proc_macro_span)]
 #![allow(unreachable_pub, internal_features, clippy::disallowed_types, clippy::print_stderr)]
+#![deny(deprecated_safe)]
 
 extern crate proc_macro;
 #[cfg(feature = "in-rust-tree")]
@@ -38,62 +39,82 @@ use std::{
 };
 
 use paths::{Utf8Path, Utf8PathBuf};
-use proc_macro_api::{
-    msg::{
-        self, deserialize_span_data_index_map, serialize_span_data_index_map, ExpnGlobals,
-        SpanMode, TokenId, CURRENT_API_VERSION,
-    },
-    ProcMacroKind,
-};
-use span::Span;
+use span::{Span, TokenId};
 
 use crate::server_impl::TokenStream;
 
+#[derive(Copy, Clone, Eq, PartialEq, Debug)]
+pub enum ProcMacroKind {
+    CustomDerive,
+    Attr,
+    Bang,
+}
+
 pub const RUSTC_VERSION_STRING: &str = env!("RUSTC_VERSION");
 
 pub struct ProcMacroSrv<'env> {
     expanders: HashMap<Utf8PathBuf, dylib::Expander>,
-    span_mode: SpanMode,
     env: &'env EnvSnapshot,
 }
 
 impl<'env> ProcMacroSrv<'env> {
     pub fn new(env: &'env EnvSnapshot) -> Self {
-        Self { expanders: Default::default(), span_mode: Default::default(), env }
+        Self { expanders: Default::default(), env }
     }
 }
 
 const EXPANDER_STACK_SIZE: usize = 8 * 1024 * 1024;
 
 impl ProcMacroSrv<'_> {
-    pub fn set_span_mode(&mut self, span_mode: SpanMode) {
-        self.span_mode = span_mode;
-    }
-
-    pub fn span_mode(&self) -> SpanMode {
-        self.span_mode
-    }
-
-    pub fn expand(
+    pub fn expand<S: ProcMacroSrvSpan>(
         &mut self,
-        msg::ExpandMacro { lib, env, current_dir, data }: msg::ExpandMacro,
-    ) -> Result<(msg::FlatTree, Vec<u32>), msg::PanicMessage> {
-        let span_mode = self.span_mode;
+        lib: impl AsRef<Utf8Path>,
+        env: Vec<(String, String)>,
+        current_dir: Option<impl AsRef<Path>>,
+        macro_name: String,
+        macro_body: tt::TopSubtree<S>,
+        attribute: Option<tt::TopSubtree<S>>,
+        def_site: S,
+        call_site: S,
+        mixed_site: S,
+    ) -> Result<Vec<tt::TokenTree<S>>, String> {
         let snapped_env = self.env;
-        let expander = self
-            .expander(lib.as_ref())
-            .map_err(|err| msg::PanicMessage(format!("failed to load macro: {err}")))?;
+        let expander =
+            self.expander(lib.as_ref()).map_err(|err| format!("failed to load macro: {err}"))?;
 
         let prev_env = EnvChange::apply(snapped_env, env, current_dir.as_ref().map(<_>::as_ref));
 
-        let result = match span_mode {
-            SpanMode::Id => expand_id(data, expander).map(|it| (it, vec![])),
-            SpanMode::RustAnalyzer => expand_ra_span(data, expander),
-        };
-
+        // Note, we spawn a new thread here so that thread locals allocation don't accumulate (this
+        // includes the proc-macro symbol interner)
+        let result = thread::scope(|s| {
+            let thread = thread::Builder::new()
+                .stack_size(EXPANDER_STACK_SIZE)
+                .name(macro_name.clone())
+                .spawn_scoped(s, move || {
+                    expander
+                        .expand(
+                            &macro_name,
+                            server_impl::TopSubtree(macro_body.0.into_vec()),
+                            attribute.map(|it| server_impl::TopSubtree(it.0.into_vec())),
+                            def_site,
+                            call_site,
+                            mixed_site,
+                        )
+                        .map(|tt| tt.0)
+                });
+            let res = match thread {
+                Ok(handle) => handle.join(),
+                Err(e) => return Err(e.to_string()),
+            };
+
+            match res {
+                Ok(res) => res,
+                Err(e) => std::panic::resume_unwind(e),
+            }
+        });
         prev_env.rollback();
 
-        result.map_err(msg::PanicMessage)
+        result
     }
 
     pub fn list_macros(
@@ -123,7 +144,7 @@ impl ProcMacroSrv<'_> {
     }
 }
 
-trait ProcMacroSrvSpan: Copy {
+pub trait ProcMacroSrvSpan: Copy + Send {
     type Server: proc_macro::bridge::server::Server<TokenStream = TokenStream<Self>>;
     fn make_server(call_site: Self, def_site: Self, mixed_site: Self) -> Self::Server;
 }
@@ -147,93 +168,6 @@ impl ProcMacroSrvSpan for Span {
         }
     }
 }
-
-fn expand_id(
-    msg::ExpandMacroData {
-        macro_body,
-        macro_name,
-        attributes,
-        has_global_spans: ExpnGlobals { serialize: _, def_site, call_site, mixed_site },
-        span_data_table: _,
-    }: msg::ExpandMacroData,
-    expander: &dylib::Expander,
-) -> Result<msg::FlatTree, String> {
-    let def_site = TokenId(def_site as u32);
-    let call_site = TokenId(call_site as u32);
-    let mixed_site = TokenId(mixed_site as u32);
-
-    let macro_body = macro_body.to_subtree_unresolved(CURRENT_API_VERSION);
-    let attributes = attributes.map(|it| it.to_subtree_unresolved(CURRENT_API_VERSION));
-    let result = thread::scope(|s| {
-        let thread = thread::Builder::new()
-            .stack_size(EXPANDER_STACK_SIZE)
-            .name(macro_name.clone())
-            .spawn_scoped(s, || {
-                expander
-                    .expand(&macro_name, macro_body, attributes, def_site, call_site, mixed_site)
-                    .map(|it| msg::FlatTree::new_raw(&it, CURRENT_API_VERSION))
-            });
-        let res = match thread {
-            Ok(handle) => handle.join(),
-            Err(e) => std::panic::resume_unwind(Box::new(e)),
-        };
-
-        match res {
-            Ok(res) => res,
-            Err(e) => std::panic::resume_unwind(e),
-        }
-    });
-    result
-}
-
-fn expand_ra_span(
-    msg::ExpandMacroData {
-        macro_body,
-        macro_name,
-        attributes,
-        has_global_spans: ExpnGlobals { serialize: _, def_site, call_site, mixed_site },
-        span_data_table,
-    }: msg::ExpandMacroData,
-    expander: &dylib::Expander,
-) -> Result<(msg::FlatTree, Vec<u32>), String> {
-    let mut span_data_table = deserialize_span_data_index_map(&span_data_table);
-
-    let def_site = span_data_table[def_site];
-    let call_site = span_data_table[call_site];
-    let mixed_site = span_data_table[mixed_site];
-
-    let macro_body = macro_body.to_subtree_resolved(CURRENT_API_VERSION, &span_data_table);
-    let attributes =
-        attributes.map(|it| it.to_subtree_resolved(CURRENT_API_VERSION, &span_data_table));
-    // Note, we spawn a new thread here so that thread locals allocation don't accumulate (this
-    // includes the proc-macro symbol interner)
-    let result = thread::scope(|s| {
-        let thread = thread::Builder::new()
-            .stack_size(EXPANDER_STACK_SIZE)
-            .name(macro_name.clone())
-            .spawn_scoped(s, || {
-                expander
-                    .expand(&macro_name, macro_body, attributes, def_site, call_site, mixed_site)
-                    .map(|it| {
-                        (
-                            msg::FlatTree::new(&it, CURRENT_API_VERSION, &mut span_data_table),
-                            serialize_span_data_index_map(&span_data_table),
-                        )
-                    })
-            });
-        let res = match thread {
-            Ok(handle) => handle.join(),
-            Err(e) => std::panic::resume_unwind(Box::new(e)),
-        };
-
-        match res {
-            Ok(res) => res,
-            Err(e) => std::panic::resume_unwind(e),
-        }
-    });
-    result
-}
-
 pub struct PanicMessage {
     message: Option<String>,
 }
@@ -254,10 +188,13 @@ impl Default for EnvSnapshot {
     }
 }
 
+static ENV_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
+
 struct EnvChange<'snap> {
     changed_vars: Vec<String>,
     prev_working_dir: Option<PathBuf>,
     snap: &'snap EnvSnapshot,
+    _guard: std::sync::MutexGuard<'snap, ()>,
 }
 
 impl<'snap> EnvChange<'snap> {
@@ -266,6 +203,7 @@ impl<'snap> EnvChange<'snap> {
         new_vars: Vec<(String, String)>,
         current_dir: Option<&Path>,
     ) -> EnvChange<'snap> {
+        let guard = ENV_LOCK.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
         let prev_working_dir = match current_dir {
             Some(dir) => {
                 let prev_working_dir = std::env::current_dir().ok();
@@ -284,11 +222,13 @@ impl<'snap> EnvChange<'snap> {
             changed_vars: new_vars
                 .into_iter()
                 .map(|(k, v)| {
-                    env::set_var(&k, v);
+                    // SAFETY: We have acquired the environment lock
+                    unsafe { env::set_var(&k, v) };
                     k
                 })
                 .collect(),
             prev_working_dir,
+            _guard: guard,
         }
     }
 
@@ -298,9 +238,12 @@ impl<'snap> EnvChange<'snap> {
 impl Drop for EnvChange<'_> {
     fn drop(&mut self) {
         for name in self.changed_vars.drain(..) {
-            match self.snap.vars.get::<std::ffi::OsStr>(name.as_ref()) {
-                Some(prev_val) => env::set_var(name, prev_val),
-                None => env::remove_var(name),
+            // SAFETY: We have acquired the environment lock
+            unsafe {
+                match self.snap.vars.get::<std::ffi::OsStr>(name.as_ref()) {
+                    Some(prev_val) => env::set_var(name, prev_val),
+                    None => env::remove_var(name),
+                }
             }
         }
 
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 097b39a3f91..58f5e80dc4e 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
@@ -1,15 +1,15 @@
 //! Proc macro ABI
 
 use proc_macro::bridge;
-use proc_macro_api::ProcMacroKind;
 
 use libloading::Library;
 
-use crate::{dylib::LoadProcMacroDylibError, ProcMacroSrvSpan};
+use crate::{
+    dylib::LoadProcMacroDylibError, server_impl::TopSubtree, ProcMacroKind, ProcMacroSrvSpan,
+};
 
-pub(crate) struct ProcMacros {
-    exported_macros: Vec<bridge::client::ProcMacro>,
-}
+#[repr(transparent)]
+pub(crate) struct ProcMacros([bridge::client::ProcMacro]);
 
 impl From<bridge::PanicMessage> for crate::PanicMessage {
     fn from(p: bridge::PanicMessage) -> Self {
@@ -27,29 +27,28 @@ impl ProcMacros {
     /// *`info` - RustCInfo about the compiler that was used to compile the
     ///           macro crate. This is the information we use to figure out
     ///           which ABI to return
-    pub(crate) fn from_lib(
-        lib: &Library,
+    pub(crate) fn from_lib<'l>(
+        lib: &'l Library,
         symbol_name: String,
         version_string: &str,
-    ) -> Result<ProcMacros, LoadProcMacroDylibError> {
-        if version_string == crate::RUSTC_VERSION_STRING {
-            let macros =
-                unsafe { lib.get::<&&[bridge::client::ProcMacro]>(symbol_name.as_bytes()) }?;
-
-            return Ok(Self { exported_macros: macros.to_vec() });
+    ) -> Result<&'l ProcMacros, LoadProcMacroDylibError> {
+        if version_string != crate::RUSTC_VERSION_STRING {
+            return Err(LoadProcMacroDylibError::AbiMismatch(version_string.to_owned()));
         }
-        Err(LoadProcMacroDylibError::AbiMismatch(version_string.to_owned()))
+        unsafe { lib.get::<&'l &'l ProcMacros>(symbol_name.as_bytes()) }
+            .map(|it| **it)
+            .map_err(Into::into)
     }
 
     pub(crate) fn expand<S: ProcMacroSrvSpan>(
         &self,
         macro_name: &str,
-        macro_body: tt::Subtree<S>,
-        attributes: Option<tt::Subtree<S>>,
+        macro_body: TopSubtree<S>,
+        attributes: Option<TopSubtree<S>>,
         def_site: S,
         call_site: S,
         mixed_site: S,
-    ) -> Result<tt::Subtree<S>, crate::PanicMessage> {
+    ) -> Result<TopSubtree<S>, crate::PanicMessage> {
         let parsed_body = crate::server_impl::TokenStream::with_subtree(macro_body);
 
         let parsed_attributes = attributes
@@ -57,7 +56,7 @@ impl ProcMacros {
                 crate::server_impl::TokenStream::with_subtree(attr)
             });
 
-        for proc_macro in &self.exported_macros {
+        for proc_macro in &self.0 {
             match proc_macro {
                 bridge::client::ProcMacro::CustomDerive { trait_name, client, .. }
                     if *trait_name == macro_name =>
@@ -103,7 +102,7 @@ impl ProcMacros {
     }
 
     pub(crate) fn list_macros(&self) -> Vec<(String, ProcMacroKind)> {
-        self.exported_macros
+        self.0
             .iter()
             .map(|proc_macro| match proc_macro {
                 bridge::client::ProcMacro::CustomDerive { trait_name, .. } => {
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl.rs
index c9a86216905..3d999421794 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl.rs
@@ -8,6 +8,8 @@
 //!
 //! FIXME: No span and source file information is implemented yet
 
+use std::fmt;
+
 use proc_macro::bridge;
 
 mod token_stream;
@@ -19,6 +21,32 @@ pub mod token_id;
 // pub use symbol::*;
 use tt::Spacing;
 
+#[derive(Clone)]
+pub(crate) struct TopSubtree<S>(pub(crate) Vec<tt::TokenTree<S>>);
+
+impl<S: Copy + fmt::Debug> fmt::Debug for TopSubtree<S> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Debug::fmt(&tt::TokenTreesView::new(&self.0), f)
+    }
+}
+
+impl<S: Copy> TopSubtree<S> {
+    pub(crate) fn top_subtree(&self) -> &tt::Subtree<S> {
+        let tt::TokenTree::Subtree(subtree) = &self.0[0] else {
+            unreachable!("the first token tree is always the top subtree");
+        };
+        subtree
+    }
+
+    pub(crate) fn from_bridge(group: bridge::Group<TokenStream<S>, S>) -> Self {
+        let delimiter = delim_to_internal(group.delimiter, group.span);
+        let mut tts =
+            group.stream.map(|it| it.token_trees).unwrap_or_else(|| Vec::with_capacity(1));
+        tts.insert(0, tt::TokenTree::Subtree(tt::Subtree { delimiter, len: tts.len() as u32 }));
+        TopSubtree(tts)
+    }
+}
+
 fn delim_to_internal<S>(d: proc_macro::Delimiter, span: bridge::DelimSpan<S>) -> tt::Delimiter<S> {
     let kind = match d {
         proc_macro::Delimiter::Parenthesis => tt::DelimiterKind::Parenthesis,
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
index 1b535d2a1cc..beaebf33300 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
@@ -6,23 +6,18 @@
 //! change their representation to be compatible with rust-analyzer's.
 use std::{
     collections::{HashMap, HashSet},
-    iter,
     ops::{Bound, Range},
 };
 
 use intern::Symbol;
 use proc_macro::bridge::{self, server};
-use span::{Span, FIXUP_ERASED_FILE_AST_ID_MARKER};
+use span::{FileId, Span, FIXUP_ERASED_FILE_AST_ID_MARKER};
 use tt::{TextRange, TextSize};
 
-use crate::server_impl::{
-    delim_to_external, delim_to_internal, literal_kind_to_external, literal_kind_to_internal,
-    token_stream::TokenStreamBuilder,
-};
+use crate::server_impl::{literal_kind_to_internal, token_stream::TokenStreamBuilder, TopSubtree};
 mod tt {
     pub use tt::*;
 
-    pub type Subtree = ::tt::Subtree<super::Span>;
     pub type TokenTree = ::tt::TokenTree<super::Span>;
     pub type Leaf = ::tt::Leaf<super::Span>;
     pub type Literal = ::tt::Literal<super::Span>;
@@ -32,8 +27,10 @@ mod tt {
 
 type TokenStream = crate::server_impl::TokenStream<Span>;
 
-#[derive(Clone)]
-pub struct SourceFile;
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub struct SourceFile {
+    file_id: FileId,
+}
 pub struct FreeFunctions;
 
 pub struct RaSpanServer {
@@ -159,15 +156,8 @@ impl server::TokenStream for RaSpanServer {
     ) -> Self::TokenStream {
         match tree {
             bridge::TokenTree::Group(group) => {
-                let group = tt::Subtree {
-                    delimiter: delim_to_internal(group.delimiter, group.span),
-                    token_trees: match group.stream {
-                        Some(stream) => stream.into_iter().collect(),
-                        None => Box::new([]),
-                    },
-                };
-                let tree = tt::TokenTree::from(group);
-                Self::TokenStream::from_iter(iter::once(tree))
+                let group = TopSubtree::from_bridge(group);
+                TokenStream { token_trees: group.0 }
             }
 
             bridge::TokenTree::Ident(ident) => {
@@ -179,7 +169,7 @@ impl server::TokenStream for RaSpanServer {
                 };
                 let leaf = tt::Leaf::from(ident);
                 let tree = tt::TokenTree::from(leaf);
-                Self::TokenStream::from_iter(iter::once(tree))
+                TokenStream { token_trees: vec![tree] }
             }
 
             bridge::TokenTree::Literal(literal) => {
@@ -192,7 +182,7 @@ impl server::TokenStream for RaSpanServer {
 
                 let leaf: tt::Leaf = tt::Leaf::from(literal);
                 let tree = tt::TokenTree::from(leaf);
-                Self::TokenStream::from_iter(iter::once(tree))
+                TokenStream { token_trees: vec![tree] }
             }
 
             bridge::TokenTree::Punct(p) => {
@@ -203,7 +193,7 @@ impl server::TokenStream for RaSpanServer {
                 };
                 let leaf = tt::Leaf::from(punct);
                 let tree = tt::TokenTree::from(leaf);
-                Self::TokenStream::from_iter(iter::once(tree))
+                TokenStream { token_trees: vec![tree] }
             }
         }
     }
@@ -251,49 +241,13 @@ impl server::TokenStream for RaSpanServer {
         &mut self,
         stream: Self::TokenStream,
     ) -> Vec<bridge::TokenTree<Self::TokenStream, Self::Span, Self::Symbol>> {
-        stream
-            .into_iter()
-            .map(|tree| match tree {
-                tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
-                    bridge::TokenTree::Ident(bridge::Ident {
-                        sym: ident.sym,
-                        is_raw: ident.is_raw.yes(),
-                        span: ident.span,
-                    })
-                }
-                tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => {
-                    bridge::TokenTree::Literal(bridge::Literal {
-                        span: lit.span,
-                        kind: literal_kind_to_external(lit.kind),
-                        symbol: lit.symbol,
-                        suffix: lit.suffix,
-                    })
-                }
-                tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) => {
-                    bridge::TokenTree::Punct(bridge::Punct {
-                        ch: punct.char as u8,
-                        joint: punct.spacing == tt::Spacing::Joint,
-                        span: punct.span,
-                    })
-                }
-                tt::TokenTree::Subtree(subtree) => bridge::TokenTree::Group(bridge::Group {
-                    delimiter: delim_to_external(subtree.delimiter),
-                    stream: if subtree.token_trees.is_empty() {
-                        None
-                    } else {
-                        Some(subtree.token_trees.into_vec().into_iter().collect())
-                    },
-                    span: bridge::DelimSpan::from_single(subtree.delimiter.open),
-                }),
-            })
-            .collect()
+        stream.into_bridge()
     }
 }
 
 impl server::SourceFile for RaSpanServer {
-    fn eq(&mut self, _file1: &Self::SourceFile, _file2: &Self::SourceFile) -> bool {
-        // FIXME
-        true
+    fn eq(&mut self, file1: &Self::SourceFile, file2: &Self::SourceFile) -> bool {
+        file1 == file2
     }
     fn path(&mut self, _file: &Self::SourceFile) -> String {
         // FIXME
@@ -308,9 +262,8 @@ impl server::Span for RaSpanServer {
     fn debug(&mut self, span: Self::Span) -> String {
         format!("{:?}", span)
     }
-    fn source_file(&mut self, _span: Self::Span) -> Self::SourceFile {
-        // FIXME stub, requires db
-        SourceFile {}
+    fn source_file(&mut self, span: Self::Span) -> Self::SourceFile {
+        SourceFile { file_id: span.anchor.file_id.file_id() }
     }
     fn save_span(&mut self, _span: Self::Span) -> usize {
         // FIXME, quote is incompatible with third-party tools
@@ -507,13 +460,14 @@ mod tests {
                         close: span,
                         kind: tt::DelimiterKind::Brace,
                     },
-                    token_trees: Box::new([tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
-                        kind: tt::LitKind::Str,
-                        symbol: Symbol::intern("string"),
-                        suffix: None,
-                        span,
-                    }))]),
+                    len: 1,
                 }),
+                tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
+                    kind: tt::LitKind::Str,
+                    symbol: Symbol::intern("string"),
+                    suffix: None,
+                    span,
+                })),
             ],
         };
 
@@ -530,35 +484,38 @@ mod tests {
             },
             ctx: SyntaxContextId::ROOT,
         };
-        let subtree_paren_a = tt::TokenTree::Subtree(tt::Subtree {
-            delimiter: tt::Delimiter {
-                open: span,
-                close: span,
-                kind: tt::DelimiterKind::Parenthesis,
-            },
-            token_trees: Box::new([tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
+        let subtree_paren_a = vec![
+            tt::TokenTree::Subtree(tt::Subtree {
+                delimiter: tt::Delimiter {
+                    open: span,
+                    close: span,
+                    kind: tt::DelimiterKind::Parenthesis,
+                },
+                len: 1,
+            }),
+            tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
                 is_raw: tt::IdentIsRaw::No,
                 sym: Symbol::intern("a"),
                 span,
-            }))]),
-        });
+            })),
+        ];
 
         let t1 = TokenStream::from_str("(a)", span).unwrap();
-        assert_eq!(t1.token_trees.len(), 1);
-        assert_eq!(t1.token_trees[0], subtree_paren_a);
+        assert_eq!(t1.token_trees.len(), 2);
+        assert!(t1.token_trees == subtree_paren_a);
 
         let t2 = TokenStream::from_str("(a);", span).unwrap();
-        assert_eq!(t2.token_trees.len(), 2);
-        assert_eq!(t2.token_trees[0], subtree_paren_a);
+        assert_eq!(t2.token_trees.len(), 3);
+        assert!(t2.token_trees[0..2] == subtree_paren_a);
 
         let underscore = TokenStream::from_str("_", span).unwrap();
-        assert_eq!(
-            underscore.token_trees[0],
-            tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
-                sym: Symbol::intern("_"),
-                span,
-                is_raw: tt::IdentIsRaw::No,
-            }))
+        assert!(
+            underscore.token_trees[0]
+                == tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
+                    sym: Symbol::intern("_"),
+                    span,
+                    is_raw: tt::IdentIsRaw::No,
+                }))
         );
     }
 }
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs
index e478b1c853b..466eb14b55e 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs
@@ -1,30 +1,22 @@
 //! proc-macro server backend based on [`proc_macro_api::msg::TokenId`] as the backing span.
 //! This backend is rather inflexible, used by RustRover and older rust-analyzer versions.
-use std::{
-    iter,
-    ops::{Bound, Range},
-};
+use std::ops::{Bound, Range};
 
 use intern::Symbol;
 use proc_macro::bridge::{self, server};
 
-use crate::server_impl::{
-    delim_to_external, delim_to_internal, literal_kind_to_external, literal_kind_to_internal,
-    token_stream::TokenStreamBuilder,
-};
+use crate::server_impl::{literal_kind_to_internal, token_stream::TokenStreamBuilder, TopSubtree};
 mod tt {
-    pub use proc_macro_api::msg::TokenId;
+    pub use span::TokenId;
 
     pub use tt::*;
 
-    pub type Subtree = ::tt::Subtree<TokenId>;
     pub type TokenTree = ::tt::TokenTree<TokenId>;
     pub type Leaf = ::tt::Leaf<TokenId>;
     pub type Literal = ::tt::Literal<TokenId>;
     pub type Punct = ::tt::Punct<TokenId>;
     pub type Ident = ::tt::Ident<TokenId>;
 }
-type Group = tt::Subtree;
 type TokenTree = tt::TokenTree;
 type Punct = tt::Punct;
 type Spacing = tt::Spacing;
@@ -148,15 +140,8 @@ impl server::TokenStream for TokenIdServer {
     ) -> Self::TokenStream {
         match tree {
             bridge::TokenTree::Group(group) => {
-                let group = Group {
-                    delimiter: delim_to_internal(group.delimiter, group.span),
-                    token_trees: match group.stream {
-                        Some(stream) => stream.into_iter().collect(),
-                        None => Box::new([]),
-                    },
-                };
-                let tree = TokenTree::from(group);
-                Self::TokenStream::from_iter(iter::once(tree))
+                let group = TopSubtree::from_bridge(group);
+                TokenStream { token_trees: group.0 }
             }
 
             bridge::TokenTree::Ident(ident) => {
@@ -167,7 +152,7 @@ impl server::TokenStream for TokenIdServer {
                 };
                 let leaf = tt::Leaf::from(ident);
                 let tree = TokenTree::from(leaf);
-                Self::TokenStream::from_iter(iter::once(tree))
+                TokenStream { token_trees: vec![tree] }
             }
 
             bridge::TokenTree::Literal(literal) => {
@@ -180,7 +165,7 @@ impl server::TokenStream for TokenIdServer {
 
                 let leaf = tt::Leaf::from(literal);
                 let tree = TokenTree::from(leaf);
-                Self::TokenStream::from_iter(iter::once(tree))
+                TokenStream { token_trees: vec![tree] }
             }
 
             bridge::TokenTree::Punct(p) => {
@@ -191,7 +176,7 @@ impl server::TokenStream for TokenIdServer {
                 };
                 let leaf = tt::Leaf::from(punct);
                 let tree = TokenTree::from(leaf);
-                Self::TokenStream::from_iter(iter::once(tree))
+                TokenStream { token_trees: vec![tree] }
             }
         }
     }
@@ -234,42 +219,7 @@ impl server::TokenStream for TokenIdServer {
         &mut self,
         stream: Self::TokenStream,
     ) -> Vec<bridge::TokenTree<Self::TokenStream, Self::Span, Self::Symbol>> {
-        stream
-            .into_iter()
-            .map(|tree| match tree {
-                tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
-                    bridge::TokenTree::Ident(bridge::Ident {
-                        sym: ident.sym,
-                        is_raw: ident.is_raw.yes(),
-                        span: ident.span,
-                    })
-                }
-                tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => {
-                    bridge::TokenTree::Literal(bridge::Literal {
-                        span: lit.span,
-                        kind: literal_kind_to_external(lit.kind),
-                        symbol: lit.symbol,
-                        suffix: lit.suffix,
-                    })
-                }
-                tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) => {
-                    bridge::TokenTree::Punct(bridge::Punct {
-                        ch: punct.char as u8,
-                        joint: punct.spacing == Spacing::Joint,
-                        span: punct.span,
-                    })
-                }
-                tt::TokenTree::Subtree(subtree) => bridge::TokenTree::Group(bridge::Group {
-                    delimiter: delim_to_external(subtree.delimiter),
-                    stream: if subtree.token_trees.is_empty() {
-                        None
-                    } else {
-                        Some(TokenStream { token_trees: subtree.token_trees.into_vec() })
-                    },
-                    span: bridge::DelimSpan::from_single(subtree.delimiter.open),
-                }),
-            })
-            .collect()
+        stream.into_bridge()
     }
 }
 
@@ -398,7 +348,7 @@ mod tests {
                         close: tt::TokenId(0),
                         kind: tt::DelimiterKind::Brace,
                     },
-                    token_trees: Box::new([]),
+                    len: 0,
                 }),
             ],
         };
@@ -408,35 +358,38 @@ mod tests {
 
     #[test]
     fn test_ra_server_from_str() {
-        let subtree_paren_a = tt::TokenTree::Subtree(tt::Subtree {
-            delimiter: tt::Delimiter {
-                open: tt::TokenId(0),
-                close: tt::TokenId(0),
-                kind: tt::DelimiterKind::Parenthesis,
-            },
-            token_trees: Box::new([tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
+        let subtree_paren_a = vec![
+            tt::TokenTree::Subtree(tt::Subtree {
+                delimiter: tt::Delimiter {
+                    open: tt::TokenId(0),
+                    close: tt::TokenId(0),
+                    kind: tt::DelimiterKind::Parenthesis,
+                },
+                len: 1,
+            }),
+            tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
                 is_raw: tt::IdentIsRaw::No,
                 sym: Symbol::intern("a"),
                 span: tt::TokenId(0),
-            }))]),
-        });
+            })),
+        ];
 
         let t1 = TokenStream::from_str("(a)", tt::TokenId(0)).unwrap();
-        assert_eq!(t1.token_trees.len(), 1);
-        assert_eq!(t1.token_trees[0], subtree_paren_a);
+        assert_eq!(t1.token_trees.len(), 2);
+        assert!(t1.token_trees[0..2] == subtree_paren_a);
 
         let t2 = TokenStream::from_str("(a);", tt::TokenId(0)).unwrap();
-        assert_eq!(t2.token_trees.len(), 2);
-        assert_eq!(t2.token_trees[0], subtree_paren_a);
+        assert_eq!(t2.token_trees.len(), 3);
+        assert!(t2.token_trees[0..2] == subtree_paren_a);
 
         let underscore = TokenStream::from_str("_", tt::TokenId(0)).unwrap();
-        assert_eq!(
-            underscore.token_trees[0],
-            tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
-                sym: Symbol::intern("_"),
-                span: tt::TokenId(0),
-                is_raw: tt::IdentIsRaw::No,
-            }))
+        assert!(
+            underscore.token_trees[0]
+                == tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident {
+                    sym: Symbol::intern("_"),
+                    span: tt::TokenId(0),
+                    is_raw: tt::IdentIsRaw::No,
+                }))
         );
     }
 }
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs
index 5649e60e0bb..645f7e7c59a 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs
@@ -1,10 +1,20 @@
 //! TokenStream implementation used by sysroot ABI
 
-use tt::TokenTree;
+use proc_macro::bridge;
 
-#[derive(Debug, Clone)]
+use crate::server_impl::{delim_to_external, literal_kind_to_external, TopSubtree};
+
+#[derive(Clone)]
 pub struct TokenStream<S> {
-    pub(super) token_trees: Vec<TokenTree<S>>,
+    pub(super) token_trees: Vec<tt::TokenTree<S>>,
+}
+
+impl<S: std::fmt::Debug + Copy> std::fmt::Debug for TokenStream<S> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.debug_struct("TokenStream")
+            .field("token_trees", &tt::TokenTreesView::new(&self.token_trees))
+            .finish()
+    }
 }
 
 impl<S> Default for TokenStream<S> {
@@ -13,84 +23,85 @@ impl<S> Default for TokenStream<S> {
     }
 }
 
-impl<S> TokenStream<S> {
+impl<S: Copy> TokenStream<S> {
     pub(crate) fn new() -> Self {
         TokenStream::default()
     }
 
-    pub(crate) fn with_subtree(subtree: tt::Subtree<S>) -> Self {
-        if subtree.delimiter.kind != tt::DelimiterKind::Invisible {
-            TokenStream { token_trees: vec![TokenTree::Subtree(subtree)] }
-        } else {
-            TokenStream { token_trees: subtree.token_trees.into_vec() }
+    pub(crate) fn with_subtree(subtree: TopSubtree<S>) -> Self {
+        let delimiter_kind = subtree.top_subtree().delimiter.kind;
+        let mut token_trees = subtree.0;
+        if delimiter_kind == tt::DelimiterKind::Invisible {
+            token_trees.remove(0);
         }
+        TokenStream { token_trees }
     }
 
-    pub(crate) fn into_subtree(self, call_site: S) -> tt::Subtree<S>
+    pub(crate) fn into_subtree(mut self, call_site: S) -> TopSubtree<S>
     where
         S: Copy,
     {
-        tt::Subtree {
-            delimiter: tt::Delimiter {
-                open: call_site,
-                close: call_site,
-                kind: tt::DelimiterKind::Invisible,
-            },
-            token_trees: self.token_trees.into_boxed_slice(),
-        }
+        self.token_trees.insert(
+            0,
+            tt::TokenTree::Subtree(tt::Subtree {
+                delimiter: tt::Delimiter {
+                    open: call_site,
+                    close: call_site,
+                    kind: tt::DelimiterKind::Invisible,
+                },
+                len: self.token_trees.len() as u32,
+            }),
+        );
+        TopSubtree(self.token_trees)
     }
 
     pub(super) fn is_empty(&self) -> bool {
         self.token_trees.is_empty()
     }
-}
 
-/// Creates a token stream containing a single token tree.
-impl<S> From<TokenTree<S>> for TokenStream<S> {
-    fn from(tree: TokenTree<S>) -> TokenStream<S> {
-        TokenStream { token_trees: vec![tree] }
-    }
-}
-
-/// Collects a number of token trees into a single stream.
-impl<S> FromIterator<TokenTree<S>> for TokenStream<S> {
-    fn from_iter<I: IntoIterator<Item = TokenTree<S>>>(trees: I) -> Self {
-        trees.into_iter().map(TokenStream::from).collect()
-    }
-}
-
-/// A "flattening" operation on token streams, collects token trees
-/// from multiple token streams into a single stream.
-impl<S> FromIterator<TokenStream<S>> for TokenStream<S> {
-    fn from_iter<I: IntoIterator<Item = TokenStream<S>>>(streams: I) -> Self {
-        let mut builder = TokenStreamBuilder::new();
-        streams.into_iter().for_each(|stream| builder.push(stream));
-        builder.build()
-    }
-}
-
-impl<S> Extend<TokenTree<S>> for TokenStream<S> {
-    fn extend<I: IntoIterator<Item = TokenTree<S>>>(&mut self, trees: I) {
-        self.extend(trees.into_iter().map(TokenStream::from));
-    }
-}
-
-impl<S> Extend<TokenStream<S>> for TokenStream<S> {
-    fn extend<I: IntoIterator<Item = TokenStream<S>>>(&mut self, streams: I) {
-        for item in streams {
-            for tkn in item {
-                match tkn {
-                    tt::TokenTree::Subtree(subtree)
-                        if subtree.delimiter.kind == tt::DelimiterKind::Invisible =>
-                    {
-                        self.token_trees.extend(subtree.token_trees.into_vec().into_iter());
-                    }
-                    _ => {
-                        self.token_trees.push(tkn);
-                    }
+    pub(crate) fn into_bridge(self) -> Vec<bridge::TokenTree<Self, S, intern::Symbol>> {
+        let mut result = Vec::new();
+        let mut iter = self.token_trees.into_iter();
+        while let Some(tree) = iter.next() {
+            match tree {
+                tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
+                    result.push(bridge::TokenTree::Ident(bridge::Ident {
+                        sym: ident.sym,
+                        is_raw: ident.is_raw.yes(),
+                        span: ident.span,
+                    }))
+                }
+                tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => {
+                    result.push(bridge::TokenTree::Literal(bridge::Literal {
+                        span: lit.span,
+                        kind: literal_kind_to_external(lit.kind),
+                        symbol: lit.symbol,
+                        suffix: lit.suffix,
+                    }))
+                }
+                tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) => {
+                    result.push(bridge::TokenTree::Punct(bridge::Punct {
+                        ch: punct.char as u8,
+                        joint: punct.spacing == tt::Spacing::Joint,
+                        span: punct.span,
+                    }))
+                }
+                tt::TokenTree::Subtree(subtree) => {
+                    result.push(bridge::TokenTree::Group(bridge::Group {
+                        delimiter: delim_to_external(subtree.delimiter),
+                        stream: if subtree.len == 0 {
+                            None
+                        } else {
+                            Some(TokenStream {
+                                token_trees: iter.by_ref().take(subtree.usize_len()).collect(),
+                            })
+                        },
+                        span: bridge::DelimSpan::from_single(subtree.delimiter.open),
+                    }))
                 }
             }
         }
+        result
     }
 }
 
@@ -103,19 +114,7 @@ pub(super) mod token_stream_impls {
 
     use core::fmt;
 
-    use super::{TokenStream, TokenTree};
-
-    /// An iterator over `TokenStream`'s `TokenTree`s.
-    /// The iteration is "shallow", e.g., the iterator doesn't recurse into delimited groups,
-    /// and returns whole groups as token trees.
-    impl<S> IntoIterator for TokenStream<S> {
-        type Item = TokenTree<S>;
-        type IntoIter = std::vec::IntoIter<TokenTree<S>>;
-
-        fn into_iter(self) -> Self::IntoIter {
-            self.token_trees.into_iter()
-        }
-    }
+    use super::{TokenStream, TopSubtree};
 
     /// Attempts to break the string into tokens and parse those tokens into a token stream.
     /// May fail for a number of reasons, for example, if the string contains unbalanced delimiters
@@ -133,7 +132,7 @@ pub(super) mod token_stream_impls {
             )
             .ok_or_else(|| format!("lexing error: {src}"))?;
 
-            Ok(TokenStream::with_subtree(subtree))
+            Ok(TokenStream::with_subtree(TopSubtree(subtree.0.into_vec())))
         }
     }
 
@@ -145,13 +144,13 @@ pub(super) mod token_stream_impls {
     }
 }
 
-impl<S> TokenStreamBuilder<S> {
+impl<S: Copy> TokenStreamBuilder<S> {
     pub(super) fn new() -> TokenStreamBuilder<S> {
         TokenStreamBuilder { acc: TokenStream::new() }
     }
 
     pub(super) fn push(&mut self, stream: TokenStream<S>) {
-        self.acc.extend(stream)
+        self.acc.token_trees.extend(stream.token_trees)
     }
 
     pub(super) fn build(self) -> TokenStream<S> {
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs
index cc5d4a89131..37d51050f32 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/utils.rs
@@ -1,17 +1,18 @@
 //! utils used in proc-macro tests
 
 use expect_test::Expect;
-use proc_macro_api::msg::TokenId;
-use span::{EditionedFileId, ErasedFileAstId, FileId, Span, SpanAnchor, SyntaxContextId};
+use span::{EditionedFileId, ErasedFileAstId, FileId, Span, SpanAnchor, SyntaxContextId, TokenId};
 use tt::TextRange;
 
 use crate::{dylib, proc_macro_test_dylib_path, EnvSnapshot, ProcMacroSrv};
 
 fn parse_string(call_site: TokenId, src: &str) -> crate::server_impl::TokenStream<TokenId> {
-    crate::server_impl::TokenStream::with_subtree(
+    crate::server_impl::TokenStream::with_subtree(crate::server_impl::TopSubtree(
         syntax_bridge::parse_to_token_tree_static_span(span::Edition::CURRENT, call_site, src)
-            .unwrap(),
-    )
+            .unwrap()
+            .0
+            .into_vec(),
+    ))
 }
 
 fn parse_string_spanned(
@@ -19,9 +20,12 @@ fn parse_string_spanned(
     call_site: SyntaxContextId,
     src: &str,
 ) -> crate::server_impl::TokenStream<Span> {
-    crate::server_impl::TokenStream::with_subtree(
-        syntax_bridge::parse_to_token_tree(span::Edition::CURRENT, anchor, call_site, src).unwrap(),
-    )
+    crate::server_impl::TokenStream::with_subtree(crate::server_impl::TopSubtree(
+        syntax_bridge::parse_to_token_tree(span::Edition::CURRENT, anchor, call_site, src)
+            .unwrap()
+            .0
+            .into_vec(),
+    ))
 }
 
 pub fn assert_expand(macro_name: &str, ra_fixture: &str, expect: Expect, expect_s: Expect) {
diff --git a/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs b/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs
index 524323b9736..b0939229f93 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/build_dependencies.rs
@@ -172,19 +172,18 @@ impl WorkspaceBuildScripts {
         }
         let res = (|| {
             let target_libdir = (|| {
-                let mut cargo_config = sysroot.tool(Tool::Cargo);
+                let mut cargo_config = sysroot.tool(Tool::Cargo, current_dir);
                 cargo_config.envs(extra_env);
                 cargo_config
-                    .current_dir(current_dir)
                     .args(["rustc", "-Z", "unstable-options", "--print", "target-libdir"])
                     .env("RUSTC_BOOTSTRAP", "1");
-                if let Ok(it) = utf8_stdout(cargo_config) {
+                if let Ok(it) = utf8_stdout(&mut cargo_config) {
                     return Ok(it);
                 }
-                let mut cmd = sysroot.tool(Tool::Rustc);
+                let mut cmd = sysroot.tool(Tool::Rustc, current_dir);
                 cmd.envs(extra_env);
                 cmd.args(["--print", "target-libdir"]);
-                utf8_stdout(cmd)
+                utf8_stdout(&mut cmd)
             })()?;
 
             let target_libdir = AbsPathBuf::try_from(Utf8PathBuf::from(target_libdir))
@@ -390,12 +389,12 @@ impl WorkspaceBuildScripts {
     ) -> io::Result<Command> {
         let mut cmd = match config.run_build_script_command.as_deref() {
             Some([program, args @ ..]) => {
-                let mut cmd = Command::new(program);
+                let mut cmd = toolchain::command(program, current_dir);
                 cmd.args(args);
                 cmd
             }
             _ => {
-                let mut cmd = sysroot.tool(Tool::Cargo);
+                let mut cmd = sysroot.tool(Tool::Cargo, current_dir);
 
                 cmd.args(["check", "--quiet", "--workspace", "--message-format=json"]);
                 cmd.args(&config.extra_args);
@@ -448,7 +447,6 @@ impl WorkspaceBuildScripts {
             }
         };
 
-        cmd.current_dir(current_dir);
         cmd.envs(&config.extra_env);
         if config.wrap_rustc_in_build_scripts {
             // Setup RUSTC_WRAPPER to point to `rust-analyzer` binary itself. We use
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 ba4946bf0b9..4d906c2aeb3 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
@@ -4,6 +4,7 @@ use std::ops;
 use std::str::from_utf8;
 
 use anyhow::Context;
+use base_db::Env;
 use cargo_metadata::{CargoOpt, MetadataCommand};
 use la_arena::{Arena, Idx};
 use paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
@@ -13,8 +14,8 @@ use serde_json::from_value;
 use span::Edition;
 use toolchain::Tool;
 
-use crate::{utf8_stdout, ManifestPath, Sysroot, SysrootQueryMetadata};
 use crate::{CfgOverrides, InvocationStrategy};
+use crate::{ManifestPath, Sysroot};
 
 /// [`CargoWorkspace`] represents the logical structure of, well, a Cargo
 /// workspace. It pretty closely mirrors `cargo metadata` output.
@@ -34,6 +35,8 @@ pub struct CargoWorkspace {
     target_directory: AbsPathBuf,
     manifest_path: ManifestPath,
     is_virtual_workspace: bool,
+    /// Environment variables set in the `.cargo/config` file.
+    config_env: Env,
 }
 
 impl ops::Index<Package> for CargoWorkspace {
@@ -86,8 +89,6 @@ pub struct CargoConfig {
     pub target: Option<String>,
     /// Sysroot loading behavior
     pub sysroot: Option<RustLibSource>,
-    /// How to query metadata for the sysroot crate.
-    pub sysroot_query_metadata: SysrootQueryMetadata,
     pub sysroot_src: Option<AbsPathBuf>,
     /// rustc private crate source
     pub rustc_source: Option<RustLibSource>,
@@ -251,6 +252,18 @@ impl TargetKind {
     }
 }
 
+#[derive(Default, Clone, Debug, PartialEq, Eq)]
+pub struct CargoMetadataConfig {
+    /// List of features to activate.
+    pub features: CargoFeatures,
+    /// rustc targets
+    pub targets: Vec<String>,
+    /// Extra args to pass to the cargo command.
+    pub extra_args: Vec<String>,
+    /// Extra env vars to set when invoking the cargo command
+    pub extra_env: FxHashMap<String, String>,
+}
+
 // Deserialize helper for the cargo metadata
 #[derive(Deserialize, Default)]
 struct PackageMetadata {
@@ -265,7 +278,7 @@ impl CargoWorkspace {
     pub fn fetch_metadata(
         cargo_toml: &ManifestPath,
         current_dir: &AbsPath,
-        config: &CargoConfig,
+        config: &CargoMetadataConfig,
         sysroot: &Sysroot,
         locked: bool,
         progress: &dyn Fn(String),
@@ -276,15 +289,13 @@ impl CargoWorkspace {
     fn fetch_metadata_(
         cargo_toml: &ManifestPath,
         current_dir: &AbsPath,
-        config: &CargoConfig,
+        config: &CargoMetadataConfig,
         sysroot: &Sysroot,
         locked: bool,
         no_deps: bool,
         progress: &dyn Fn(String),
     ) -> anyhow::Result<(cargo_metadata::Metadata, Option<anyhow::Error>)> {
-        let targets = find_list_of_build_targets(config, cargo_toml, sysroot);
-
-        let cargo = sysroot.tool(Tool::Cargo);
+        let cargo = sysroot.tool(Tool::Cargo, current_dir);
         let mut meta = MetadataCommand::new();
         meta.cargo_path(cargo.get_program());
         cargo.get_envs().for_each(|(var, val)| _ = meta.env(var, val.unwrap_or_default()));
@@ -319,12 +330,9 @@ impl CargoWorkspace {
             }
         }
 
-        if !targets.is_empty() {
-            other_options.append(
-                &mut targets
-                    .into_iter()
-                    .flat_map(|target| ["--filter-platform".to_owned(), target])
-                    .collect(),
+        if !config.targets.is_empty() {
+            other_options.extend(
+                config.targets.iter().flat_map(|it| ["--filter-platform".to_owned(), it.clone()]),
             );
         }
         // The manifest is a rust file, so this means its a script manifest
@@ -388,6 +396,7 @@ impl CargoWorkspace {
     pub fn new(
         mut meta: cargo_metadata::Metadata,
         ws_manifest_path: ManifestPath,
+        cargo_config_env: Env,
     ) -> CargoWorkspace {
         let mut pkg_by_id = FxHashMap::default();
         let mut packages = Arena::default();
@@ -509,6 +518,7 @@ impl CargoWorkspace {
             target_directory,
             manifest_path: ws_manifest_path,
             is_virtual_workspace,
+            config_env: cargo_config_env,
         }
     }
 
@@ -595,80 +605,8 @@ impl CargoWorkspace {
     pub fn is_virtual_workspace(&self) -> bool {
         self.is_virtual_workspace
     }
-}
-
-fn find_list_of_build_targets(
-    config: &CargoConfig,
-    cargo_toml: &ManifestPath,
-    sysroot: &Sysroot,
-) -> Vec<String> {
-    if let Some(target) = &config.target {
-        return [target.into()].to_vec();
-    }
-
-    let build_targets = cargo_config_build_target(cargo_toml, &config.extra_env, sysroot);
-    if !build_targets.is_empty() {
-        return build_targets;
-    }
-
-    rustc_discover_host_triple(cargo_toml, &config.extra_env, sysroot).into_iter().collect()
-}
-
-fn rustc_discover_host_triple(
-    cargo_toml: &ManifestPath,
-    extra_env: &FxHashMap<String, String>,
-    sysroot: &Sysroot,
-) -> Option<String> {
-    let mut rustc = sysroot.tool(Tool::Rustc);
-    rustc.envs(extra_env);
-    rustc.current_dir(cargo_toml.parent()).arg("-vV");
-    tracing::debug!("Discovering host platform by {:?}", rustc);
-    match utf8_stdout(rustc) {
-        Ok(stdout) => {
-            let field = "host: ";
-            let target = stdout.lines().find_map(|l| l.strip_prefix(field));
-            if let Some(target) = target {
-                Some(target.to_owned())
-            } else {
-                // If we fail to resolve the host platform, it's not the end of the world.
-                tracing::info!("rustc -vV did not report host platform, got:\n{}", stdout);
-                None
-            }
-        }
-        Err(e) => {
-            tracing::warn!("Failed to discover host platform: {}", e);
-            None
-        }
-    }
-}
-
-fn cargo_config_build_target(
-    cargo_toml: &ManifestPath,
-    extra_env: &FxHashMap<String, String>,
-    sysroot: &Sysroot,
-) -> Vec<String> {
-    let mut cargo_config = sysroot.tool(Tool::Cargo);
-    cargo_config.envs(extra_env);
-    cargo_config
-        .current_dir(cargo_toml.parent())
-        .args(["-Z", "unstable-options", "config", "get", "build.target"])
-        .env("RUSTC_BOOTSTRAP", "1");
-    // if successful we receive `build.target = "target-triple"`
-    // or `build.target = ["<target 1>", ..]`
-    tracing::debug!("Discovering cargo config target by {:?}", cargo_config);
-    utf8_stdout(cargo_config).map(parse_output_cargo_config_build_target).unwrap_or_default()
-}
-
-fn parse_output_cargo_config_build_target(stdout: String) -> Vec<String> {
-    let trimmed = stdout.trim_start_matches("build.target = ").trim_matches('"');
-
-    if !trimmed.starts_with('[') {
-        return [trimmed.to_owned()].to_vec();
-    }
 
-    let res = serde_json::from_str(trimmed);
-    if let Err(e) = &res {
-        tracing::warn!("Failed to parse `build.target` as an array of target: {}`", e);
+    pub fn env(&self) -> &Env {
+        &self.config_env
     }
-    res.unwrap_or_default()
 }
diff --git a/src/tools/rust-analyzer/crates/project-model/src/env.rs b/src/tools/rust-analyzer/crates/project-model/src/env.rs
index ff9d2035f60..37fffba2955 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/env.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/env.rs
@@ -1,9 +1,10 @@
 //! Cargo-like environment variables injection.
 use base_db::Env;
+use paths::Utf8Path;
 use rustc_hash::FxHashMap;
 use toolchain::Tool;
 
-use crate::{utf8_stdout, CargoWorkspace, ManifestPath, PackageData, Sysroot, TargetKind};
+use crate::{utf8_stdout, ManifestPath, PackageData, Sysroot, TargetKind};
 
 /// Recreates the compile-time environment variables that Cargo sets.
 ///
@@ -50,34 +51,23 @@ pub(crate) fn inject_cargo_env(env: &mut Env) {
     env.set("CARGO", Tool::Cargo.path().to_string());
 }
 
-pub(crate) fn inject_rustc_tool_env(
-    env: &mut Env,
-    cargo: &CargoWorkspace,
-    cargo_name: &str,
-    kind: TargetKind,
-) {
+pub(crate) fn inject_rustc_tool_env(env: &mut Env, cargo_name: &str, kind: TargetKind) {
     _ = kind;
     // FIXME
     // if kind.is_executable() {
     //     env.set("CARGO_BIN_NAME", cargo_name);
     // }
     env.set("CARGO_CRATE_NAME", cargo_name.replace('-', "_"));
-    // NOTE: Technically we should set this for all crates, but that will worsen the deduplication
-    // logic so for now just keeping it proc-macros ought to be fine.
-    if kind.is_proc_macro() {
-        env.set("CARGO_RUSTC_CURRENT_DIR", cargo.manifest_path().parent().to_string());
-    }
 }
 
 pub(crate) fn cargo_config_env(
     manifest: &ManifestPath,
     extra_env: &FxHashMap<String, String>,
     sysroot: &Sysroot,
-) -> FxHashMap<String, String> {
-    let mut cargo_config = sysroot.tool(Tool::Cargo);
+) -> Env {
+    let mut cargo_config = sysroot.tool(Tool::Cargo, manifest.parent());
     cargo_config.envs(extra_env);
     cargo_config
-        .current_dir(manifest.parent())
         .args(["-Z", "unstable-options", "config", "get", "env"])
         .env("RUSTC_BOOTSTRAP", "1");
     if manifest.is_rust_manifest() {
@@ -85,8 +75,8 @@ pub(crate) fn cargo_config_env(
     }
     // if successful we receive `env.key.value = "value" per entry
     tracing::debug!("Discovering cargo config env by {:?}", cargo_config);
-    utf8_stdout(cargo_config)
-        .map(parse_output_cargo_config_env)
+    utf8_stdout(&mut cargo_config)
+        .map(|stdout| parse_output_cargo_config_env(manifest, &stdout))
         .inspect(|env| {
             tracing::debug!("Discovered cargo config env: {:?}", env);
         })
@@ -96,18 +86,61 @@ pub(crate) fn cargo_config_env(
         .unwrap_or_default()
 }
 
-fn parse_output_cargo_config_env(stdout: String) -> FxHashMap<String, String> {
-    stdout
-        .lines()
-        .filter_map(|l| l.strip_prefix("env."))
-        .filter_map(|l| l.split_once(" = "))
-        .filter_map(|(k, v)| {
-            if k.contains('.') {
-                k.strip_suffix(".value").zip(Some(v))
-            } else {
-                Some((k, v))
+fn parse_output_cargo_config_env(manifest: &ManifestPath, stdout: &str) -> Env {
+    let mut env = Env::default();
+    let mut relatives = vec![];
+    for (key, val) in
+        stdout.lines().filter_map(|l| l.strip_prefix("env.")).filter_map(|l| l.split_once(" = "))
+    {
+        let val = val.trim_matches('"').to_owned();
+        if let Some((key, modifier)) = key.split_once('.') {
+            match modifier {
+                "relative" => relatives.push((key, val)),
+                "value" => _ = env.insert(key, val),
+                _ => {
+                    tracing::warn!(
+                        "Unknown modifier in cargo config env: {}, expected `relative` or `value`",
+                        modifier
+                    );
+                    continue;
+                }
             }
-        })
-        .map(|(key, value)| (key.to_owned(), value.trim_matches('"').to_owned()))
-        .collect()
+        } else {
+            env.insert(key, val);
+        }
+    }
+    // FIXME: The base here should be the parent of the `.cargo/config` file, not the manifest.
+    // But cargo does not provide this information.
+    let base = <_ as AsRef<Utf8Path>>::as_ref(manifest.parent());
+    for (key, relative) in relatives {
+        if relative != "true" {
+            continue;
+        }
+        if let Some(suffix) = env.get(key) {
+            env.insert(key, base.join(suffix).to_string());
+        }
+    }
+    env
+}
+
+#[test]
+fn parse_output_cargo_config_env_works() {
+    let stdout = r#"
+env.CARGO_WORKSPACE_DIR.relative = true
+env.CARGO_WORKSPACE_DIR.value = ""
+env.RELATIVE.relative = true
+env.RELATIVE.value = "../relative"
+env.INVALID.relative = invalidbool
+env.INVALID.value = "../relative"
+env.TEST.value = "test"
+"#
+    .trim();
+    let cwd = paths::Utf8PathBuf::try_from(std::env::current_dir().unwrap()).unwrap();
+    let manifest = paths::AbsPathBuf::assert(cwd.join("Cargo.toml"));
+    let manifest = ManifestPath::try_from(manifest).unwrap();
+    let env = parse_output_cargo_config_env(&manifest, stdout);
+    assert_eq!(env.get("CARGO_WORKSPACE_DIR").as_deref(), Some(cwd.join("").as_str()));
+    assert_eq!(env.get("RELATIVE").as_deref(), Some(cwd.join("../relative").as_str()));
+    assert_eq!(env.get("INVALID").as_deref(), Some("../relative"));
+    assert_eq!(env.get("TEST").as_deref(), Some("test"));
 }
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 da8afc5d3a1..fc1fd7b877f 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/lib.rs
@@ -15,14 +15,32 @@
 //!   procedural macros).
 //! * Lowering of concrete model to a [`base_db::CrateGraph`]
 
+pub mod project_json;
+pub mod toolchain_info {
+    pub mod rustc_cfg;
+    pub mod target_data_layout;
+    pub mod target_tuple;
+    pub mod version;
+
+    use std::path::Path;
+
+    use crate::{ManifestPath, Sysroot};
+
+    #[derive(Copy, Clone)]
+    pub enum QueryConfig<'a> {
+        /// Directly invoke `rustc` to query the desired information.
+        Rustc(&'a Sysroot, &'a Path),
+        /// Attempt to use cargo to query the desired information, honoring cargo configurations.
+        /// If this fails, falls back to invoking `rustc` directly.
+        Cargo(&'a Sysroot, &'a ManifestPath),
+    }
+}
+
 mod build_dependencies;
 mod cargo_workspace;
 mod env;
 mod manifest_path;
-pub mod project_json;
-mod rustc_cfg;
 mod sysroot;
-pub mod target_data_layout;
 mod workspace;
 
 #[cfg(test)]
@@ -42,8 +60,8 @@ use rustc_hash::FxHashSet;
 pub use crate::{
     build_dependencies::WorkspaceBuildScripts,
     cargo_workspace::{
-        CargoConfig, CargoFeatures, CargoWorkspace, Package, PackageData, PackageDependency,
-        RustLibSource, Target, TargetData, TargetKind,
+        CargoConfig, CargoFeatures, CargoMetadataConfig, CargoWorkspace, Package, PackageData,
+        PackageDependency, RustLibSource, Target, TargetData, TargetKind,
     },
     manifest_path::ManifestPath,
     project_json::{ProjectJson, ProjectJsonData},
@@ -181,7 +199,7 @@ impl fmt::Display for ProjectManifest {
     }
 }
 
-fn utf8_stdout(mut cmd: Command) -> anyhow::Result<String> {
+fn utf8_stdout(cmd: &mut Command) -> anyhow::Result<String> {
     let output = cmd.output().with_context(|| format!("{cmd:?} failed"))?;
     if !output.status.success() {
         match String::from_utf8(output.stderr) {
@@ -241,9 +259,20 @@ fn parse_cfg(s: &str) -> Result<cfg::CfgAtom, String> {
     Ok(res)
 }
 
-#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
-pub enum SysrootQueryMetadata {
-    #[default]
-    CargoMetadata,
-    None,
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum SysrootSourceWorkspaceConfig {
+    CargoMetadata(CargoMetadataConfig),
+    Stitched,
+}
+
+impl Default for SysrootSourceWorkspaceConfig {
+    fn default() -> Self {
+        SysrootSourceWorkspaceConfig::default_cargo()
+    }
+}
+
+impl SysrootSourceWorkspaceConfig {
+    pub fn default_cargo() -> Self {
+        SysrootSourceWorkspaceConfig::CargoMetadata(Default::default())
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/project-model/src/manifest_path.rs b/src/tools/rust-analyzer/crates/project-model/src/manifest_path.rs
index a72dab60752..73a4e6e1216 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/manifest_path.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/manifest_path.rs
@@ -46,7 +46,7 @@ impl ManifestPath {
     }
 
     pub fn is_rust_manifest(&self) -> bool {
-        self.file.extension().map_or(false, |ext| ext == "rs")
+        self.file.extension() == Some("rs")
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs b/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs
deleted file mode 100644
index bc1f0e6fbf2..00000000000
--- a/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs
+++ /dev/null
@@ -1,99 +0,0 @@
-//! Runs `rustc --print cfg` to get built-in cfg flags.
-
-use anyhow::Context;
-use cfg::CfgAtom;
-use intern::Symbol;
-use rustc_hash::FxHashMap;
-use toolchain::Tool;
-
-use crate::{utf8_stdout, ManifestPath, Sysroot};
-
-/// Determines how `rustc --print cfg` is discovered and invoked.
-pub(crate) enum RustcCfgConfig<'a> {
-    /// Use `rustc --print cfg`, either from with the binary from the sysroot or by discovering via
-    /// [`toolchain::rustc`].
-    Rustc(&'a Sysroot),
-    /// Use `cargo --print cfg`, either from with the binary from the sysroot or by discovering via
-    /// [`toolchain::cargo`].
-    Cargo(&'a Sysroot, &'a ManifestPath),
-}
-
-pub(crate) fn get(
-    target: Option<&str>,
-    extra_env: &FxHashMap<String, String>,
-    config: RustcCfgConfig<'_>,
-) -> Vec<CfgAtom> {
-    let _p = tracing::info_span!("rustc_cfg::get").entered();
-    let mut res: Vec<_> = Vec::with_capacity(7 * 2 + 1);
-
-    // Some nightly-only cfgs, which are required for stdlib
-    res.push(CfgAtom::Flag(Symbol::intern("target_thread_local")));
-    for key in ["target_has_atomic", "target_has_atomic_load_store"] {
-        for ty in ["8", "16", "32", "64", "cas", "ptr"] {
-            res.push(CfgAtom::KeyValue { key: Symbol::intern(key), value: Symbol::intern(ty) });
-        }
-        res.push(CfgAtom::Flag(Symbol::intern(key)));
-    }
-
-    let rustc_cfgs = get_rust_cfgs(target, extra_env, config);
-
-    let rustc_cfgs = match rustc_cfgs {
-        Ok(cfgs) => cfgs,
-        Err(e) => {
-            tracing::error!(?e, "failed to get rustc cfgs");
-            return res;
-        }
-    };
-
-    let rustc_cfgs = rustc_cfgs.lines().map(crate::parse_cfg).collect::<Result<Vec<_>, _>>();
-
-    match rustc_cfgs {
-        Ok(rustc_cfgs) => {
-            tracing::debug!(?rustc_cfgs, "rustc cfgs found");
-            res.extend(rustc_cfgs);
-        }
-        Err(e) => {
-            tracing::error!(?e, "failed to get rustc cfgs")
-        }
-    }
-
-    res
-}
-
-fn get_rust_cfgs(
-    target: Option<&str>,
-    extra_env: &FxHashMap<String, String>,
-    config: RustcCfgConfig<'_>,
-) -> anyhow::Result<String> {
-    let sysroot = match config {
-        RustcCfgConfig::Cargo(sysroot, cargo_toml) => {
-            let mut cmd = sysroot.tool(Tool::Cargo);
-
-            cmd.envs(extra_env);
-            cmd.current_dir(cargo_toml.parent())
-                .args(["rustc", "-Z", "unstable-options", "--print", "cfg"])
-                .env("RUSTC_BOOTSTRAP", "1");
-            if let Some(target) = target {
-                cmd.args(["--target", target]);
-            }
-
-            match utf8_stdout(cmd) {
-                Ok(it) => return Ok(it),
-                Err(e) => {
-                    tracing::warn!("failed to run `cargo rustc --print cfg`, falling back to invoking rustc directly: {e}");
-                    sysroot
-                }
-            }
-        }
-        RustcCfgConfig::Rustc(sysroot) => sysroot,
-    };
-
-    let mut cmd = sysroot.tool(Tool::Rustc);
-    cmd.envs(extra_env);
-    cmd.args(["--print", "cfg", "-O"]);
-    if let Some(target) = target {
-        cmd.args(["--target", target]);
-    }
-
-    utf8_stdout(cmd).context("unable to fetch cfgs via `rustc --print cfg -O`")
-}
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 8426e689a64..8f633d24be9 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
@@ -4,7 +4,12 @@
 //! 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, ops, process::Command};
+use std::{
+    env, fs,
+    ops::{self, Not},
+    path::Path,
+    process::Command,
+};
 
 use anyhow::{format_err, Result};
 use base_db::CrateName;
@@ -12,20 +17,24 @@ use itertools::Itertools;
 use la_arena::{Arena, Idx};
 use paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
 use rustc_hash::FxHashMap;
+use stdx::format_to;
 use toolchain::{probe_for_binary, Tool};
 
-use crate::{utf8_stdout, CargoConfig, CargoWorkspace, ManifestPath, SysrootQueryMetadata};
+use crate::{
+    cargo_workspace::CargoMetadataConfig, utf8_stdout, CargoWorkspace, ManifestPath,
+    SysrootSourceWorkspaceConfig,
+};
 
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub struct Sysroot {
     root: Option<AbsPathBuf>,
     src_root: Option<AbsPathBuf>,
-    mode: SysrootMode,
+    workspace: SysrootWorkspace,
     error: Option<String>,
 }
 
 #[derive(Debug, Clone, Eq, PartialEq)]
-pub(crate) enum SysrootMode {
+pub(crate) enum SysrootWorkspace {
     Workspace(CargoWorkspace),
     Stitched(Stitched),
     Empty,
@@ -79,7 +88,7 @@ pub(crate) struct SysrootCrateData {
 
 impl Sysroot {
     pub const fn empty() -> Sysroot {
-        Sysroot { root: None, src_root: None, mode: SysrootMode::Empty, error: None }
+        Sysroot { root: None, src_root: None, workspace: SysrootWorkspace::Empty, error: None }
     }
 
     /// Returns sysroot "root" directory, where `bin/`, `etc/`, `lib/`, `libexec/`
@@ -96,10 +105,10 @@ impl Sysroot {
     }
 
     pub fn is_empty(&self) -> bool {
-        match &self.mode {
-            SysrootMode::Workspace(ws) => ws.packages().next().is_none(),
-            SysrootMode::Stitched(stitched) => stitched.crates.is_empty(),
-            SysrootMode::Empty => true,
+        match &self.workspace {
+            SysrootWorkspace::Workspace(ws) => ws.packages().next().is_none(),
+            SysrootWorkspace::Stitched(stitched) => stitched.crates.is_empty(),
+            SysrootWorkspace::Empty => true,
         }
     }
 
@@ -108,66 +117,53 @@ impl Sysroot {
     }
 
     pub fn num_packages(&self) -> usize {
-        match &self.mode {
-            SysrootMode::Workspace(ws) => ws.packages().count(),
-            SysrootMode::Stitched(c) => c.crates().count(),
-            SysrootMode::Empty => 0,
+        match &self.workspace {
+            SysrootWorkspace::Workspace(ws) => ws.packages().count(),
+            SysrootWorkspace::Stitched(c) => c.crates().count(),
+            SysrootWorkspace::Empty => 0,
         }
     }
 
-    pub(crate) fn mode(&self) -> &SysrootMode {
-        &self.mode
+    pub(crate) fn workspace(&self) -> &SysrootWorkspace {
+        &self.workspace
     }
 }
 
-// FIXME: Expose a builder api as loading the sysroot got way too modular and complicated.
 impl Sysroot {
     /// Attempts to discover the toolchain's sysroot from the given `dir`.
-    pub fn discover(
-        dir: &AbsPath,
-        extra_env: &FxHashMap<String, String>,
-        sysroot_query_metadata: SysrootQueryMetadata,
-    ) -> Sysroot {
+    pub fn discover(dir: &AbsPath, extra_env: &FxHashMap<String, String>) -> Sysroot {
         let sysroot_dir = discover_sysroot_dir(dir, extra_env);
         let sysroot_src_dir = sysroot_dir.as_ref().ok().map(|sysroot_dir| {
             discover_sysroot_src_dir_or_add_component(sysroot_dir, dir, extra_env)
         });
-        Sysroot::load_core_check(Some(sysroot_dir), sysroot_src_dir, sysroot_query_metadata)
+        Sysroot::assemble(Some(sysroot_dir), sysroot_src_dir)
     }
 
     pub fn discover_with_src_override(
         current_dir: &AbsPath,
         extra_env: &FxHashMap<String, String>,
         sysroot_src_dir: AbsPathBuf,
-        sysroot_query_metadata: SysrootQueryMetadata,
     ) -> Sysroot {
         let sysroot_dir = discover_sysroot_dir(current_dir, extra_env);
-        Sysroot::load_core_check(
-            Some(sysroot_dir),
-            Some(Ok(sysroot_src_dir)),
-            sysroot_query_metadata,
-        )
+        Sysroot::assemble(Some(sysroot_dir), Some(Ok(sysroot_src_dir)))
     }
 
-    pub fn discover_sysroot_src_dir(
-        sysroot_dir: AbsPathBuf,
-        sysroot_query_metadata: SysrootQueryMetadata,
-    ) -> Sysroot {
+    pub fn discover_sysroot_src_dir(sysroot_dir: AbsPathBuf) -> Sysroot {
         let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir)
             .ok_or_else(|| format_err!("can't find standard library sources in {sysroot_dir}"));
-        Sysroot::load_core_check(
-            Some(Ok(sysroot_dir)),
-            Some(sysroot_src_dir),
-            sysroot_query_metadata,
-        )
+        Sysroot::assemble(Some(Ok(sysroot_dir)), Some(sysroot_src_dir))
     }
 
     pub fn discover_rustc_src(&self) -> Option<ManifestPath> {
         get_rustc_src(self.root()?)
     }
 
+    pub fn new(sysroot_dir: Option<AbsPathBuf>, sysroot_src_dir: Option<AbsPathBuf>) -> Sysroot {
+        Self::assemble(sysroot_dir.map(Ok), sysroot_src_dir.map(Ok))
+    }
+
     /// Returns a command to run a tool preferring the cargo proxies if the sysroot exists.
-    pub fn tool(&self, tool: Tool) -> Command {
+    pub fn tool(&self, tool: Tool, current_dir: impl AsRef<Path>) -> Command {
         match self.root() {
             Some(root) => {
                 // special case rustc, we can look that up directly in the sysroot's bin folder
@@ -176,15 +172,15 @@ impl Sysroot {
                     if let Some(path) =
                         probe_for_binary(root.join("bin").join(Tool::Rustc.name()).into())
                     {
-                        return Command::new(path);
+                        return toolchain::command(path, current_dir);
                     }
                 }
 
-                let mut cmd = Command::new(tool.prefer_proxy());
+                let mut cmd = toolchain::command(tool.prefer_proxy(), current_dir);
                 cmd.env("RUSTUP_TOOLCHAIN", AsRef::<std::path::Path>::as_ref(root));
                 cmd
             }
-            _ => Command::new(tool.path()),
+            _ => toolchain::command(tool.path(), current_dir),
         }
     }
 
@@ -202,90 +198,51 @@ impl Sysroot {
             })
     }
 
-    pub fn load(
-        sysroot_dir: Option<AbsPathBuf>,
-        sysroot_src_dir: Option<AbsPathBuf>,
-        sysroot_query_metadata: SysrootQueryMetadata,
-    ) -> Sysroot {
-        Self::load_core_check(sysroot_dir.map(Ok), sysroot_src_dir.map(Ok), sysroot_query_metadata)
-    }
-
-    fn load_core_check(
+    fn assemble(
         sysroot_dir: Option<Result<AbsPathBuf, anyhow::Error>>,
         sysroot_src_dir: Option<Result<AbsPathBuf, anyhow::Error>>,
-        sysroot_query_metadata: SysrootQueryMetadata,
     ) -> Sysroot {
-        let mut sysroot = Self::load_(sysroot_dir, sysroot_src_dir, sysroot_query_metadata);
-        if sysroot.error.is_none() {
-            if let Some(src_root) = &sysroot.src_root {
-                let has_core = match &sysroot.mode {
-                    SysrootMode::Workspace(ws) => ws.packages().any(|p| ws[p].name == "core"),
-                    SysrootMode::Stitched(stitched) => stitched.by_name("core").is_some(),
-                    SysrootMode::Empty => true,
-                };
-                if !has_core {
-                    let var_note = if env::var_os("RUST_SRC_PATH").is_some() {
-                        " (env var `RUST_SRC_PATH` is set and may be incorrect, try unsetting it)"
-                    } else {
-                        ", try running `rustup component add rust-src` to possibly fix this"
-                    };
-                    sysroot.error = Some(format!(
-                        "sysroot at `{src_root}` is missing a `core` library{var_note}",
-                    ));
-                }
-            }
-        }
-        sysroot
-    }
-
-    fn load_(
-        sysroot_dir: Option<Result<AbsPathBuf, anyhow::Error>>,
-        sysroot_src_dir: Option<Result<AbsPathBuf, anyhow::Error>>,
-        sysroot_query_metadata: SysrootQueryMetadata,
-    ) -> Sysroot {
-        let sysroot_dir = match sysroot_dir {
+        let mut errors = String::new();
+        let root = match sysroot_dir {
             Some(Ok(sysroot_dir)) => Some(sysroot_dir),
             Some(Err(e)) => {
-                return Sysroot {
-                    root: None,
-                    src_root: None,
-                    mode: SysrootMode::Empty,
-                    error: Some(e.to_string()),
-                }
+                format_to!(errors, "{e}\n");
+                None
             }
             None => None,
         };
-        let sysroot_src_dir = match sysroot_src_dir {
-            Some(Ok(sysroot_src_dir)) => sysroot_src_dir,
+        let src_root = match sysroot_src_dir {
+            Some(Ok(sysroot_src_dir)) => Some(sysroot_src_dir),
             Some(Err(e)) => {
-                return Sysroot {
-                    root: sysroot_dir,
-                    src_root: None,
-                    mode: SysrootMode::Empty,
-                    error: Some(e.to_string()),
-                }
-            }
-            None => {
-                return Sysroot {
-                    root: sysroot_dir,
-                    src_root: None,
-                    mode: SysrootMode::Empty,
-                    error: None,
-                }
+                format_to!(errors, "{e}\n");
+                None
             }
+            None => None,
         };
-        if sysroot_query_metadata == SysrootQueryMetadata::CargoMetadata {
-            let library_manifest =
-                ManifestPath::try_from(sysroot_src_dir.join("Cargo.toml")).unwrap();
+        Sysroot {
+            root,
+            src_root,
+            workspace: SysrootWorkspace::Empty,
+            error: errors.is_empty().not().then_some(errors),
+        }
+    }
+
+    pub fn load_workspace(&mut self, sysroot_source_config: &SysrootSourceWorkspaceConfig) {
+        assert!(matches!(self.workspace, SysrootWorkspace::Empty), "workspace already loaded");
+        let Self { root: _, src_root: Some(src_root), workspace, error: _ } = self else { return };
+        if let SysrootSourceWorkspaceConfig::CargoMetadata(cargo_config) = sysroot_source_config {
+            let library_manifest = ManifestPath::try_from(src_root.join("Cargo.toml")).unwrap();
             if fs::metadata(&library_manifest).is_ok() {
-                if let Some(sysroot) =
-                    Self::load_library_via_cargo(library_manifest, &sysroot_dir, &sysroot_src_dir)
+                if let Some(loaded) =
+                    Self::load_library_via_cargo(library_manifest, src_root, cargo_config)
                 {
-                    return sysroot;
+                    *workspace = loaded;
+                    self.load_core_check();
+                    return;
                 }
             }
         }
-        tracing::debug!("Stitching sysroot library: {sysroot_src_dir}");
+        tracing::debug!("Stitching sysroot library: {src_root}");
 
         let mut stitched = Stitched { crates: Arena::default() };
 
@@ -293,7 +250,7 @@ impl Sysroot {
             let name = path.split('/').last().unwrap();
             let root = [format!("{path}/src/lib.rs"), format!("lib{path}/lib.rs")]
                 .into_iter()
-                .map(|it| sysroot_src_dir.join(it))
+                .map(|it| src_root.join(it))
                 .filter_map(|it| ManifestPath::try_from(it).ok())
                 .find(|it| fs::metadata(it).is_ok());
 
@@ -329,21 +286,39 @@ impl Sysroot {
                 }
             }
         }
-        Sysroot {
-            root: sysroot_dir,
-            src_root: Some(sysroot_src_dir),
-            mode: SysrootMode::Stitched(stitched),
-            error: None,
+        *workspace = SysrootWorkspace::Stitched(stitched);
+        self.load_core_check();
+    }
+
+    fn load_core_check(&mut self) {
+        if self.error.is_none() {
+            if let Some(src_root) = &self.src_root {
+                let has_core = match &self.workspace {
+                    SysrootWorkspace::Workspace(ws) => ws.packages().any(|p| ws[p].name == "core"),
+                    SysrootWorkspace::Stitched(stitched) => stitched.by_name("core").is_some(),
+                    SysrootWorkspace::Empty => true,
+                };
+                if !has_core {
+                    let var_note = if env::var_os("RUST_SRC_PATH").is_some() {
+                        " (env var `RUST_SRC_PATH` is set and may be incorrect, try unsetting it)"
+                    } else {
+                        ", try running `rustup component add rust-src` to possibly fix this"
+                    };
+                    self.error = Some(format!(
+                        "sysroot at `{src_root}` is missing a `core` library{var_note}",
+                    ));
+                }
+            }
         }
     }
 
     fn load_library_via_cargo(
         library_manifest: ManifestPath,
-        sysroot_dir: &Option<AbsPathBuf>,
         sysroot_src_dir: &AbsPathBuf,
-    ) -> Option<Sysroot> {
+        cargo_config: &CargoMetadataConfig,
+    ) -> Option<SysrootWorkspace> {
         tracing::debug!("Loading library metadata: {library_manifest}");
-        let mut cargo_config = CargoConfig::default();
+        let mut cargo_config = cargo_config.clone();
         // the sysroot uses `public-dependency`, so we make cargo think it's a nightly
         cargo_config.extra_env.insert(
             "__CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS".to_owned(),
@@ -415,13 +390,8 @@ impl Sysroot {
             res.packages.remove(idx);
         });
 
-        let cargo_workspace = CargoWorkspace::new(res, library_manifest);
-        Some(Sysroot {
-            root: sysroot_dir.clone(),
-            src_root: Some(sysroot_src_dir.clone()),
-            mode: SysrootMode::Workspace(cargo_workspace),
-            error: None,
-        })
+        let cargo_workspace = CargoWorkspace::new(res, library_manifest, Default::default());
+        Some(SysrootWorkspace::Workspace(cargo_workspace))
     }
 }
 
@@ -429,11 +399,11 @@ fn discover_sysroot_dir(
     current_dir: &AbsPath,
     extra_env: &FxHashMap<String, String>,
 ) -> Result<AbsPathBuf> {
-    let mut rustc = Command::new(Tool::Rustc.path());
+    let mut rustc = toolchain::command(Tool::Rustc.path(), current_dir);
     rustc.envs(extra_env);
     rustc.current_dir(current_dir).args(["--print", "sysroot"]);
     tracing::debug!("Discovering sysroot by {:?}", rustc);
-    let stdout = utf8_stdout(rustc)?;
+    let stdout = utf8_stdout(&mut rustc)?;
     Ok(AbsPathBuf::assert(Utf8PathBuf::from(stdout)))
 }
 
@@ -461,11 +431,11 @@ fn discover_sysroot_src_dir_or_add_component(
 ) -> Result<AbsPathBuf> {
     discover_sysroot_src_dir(sysroot_path)
         .or_else(|| {
-            let mut rustup = Command::new(Tool::Rustup.prefer_proxy());
+            let mut rustup = toolchain::command(Tool::Rustup.prefer_proxy(), current_dir);
             rustup.envs(extra_env);
-            rustup.current_dir(current_dir).args(["component", "add", "rust-src"]);
+            rustup.args(["component", "add", "rust-src"]);
             tracing::info!("adding rust-src component by {:?}", rustup);
-            utf8_stdout(rustup).ok()?;
+            utf8_stdout(&mut rustup).ok()?;
             get_rust_src(sysroot_path)
         })
         .ok_or_else(|| {
diff --git a/src/tools/rust-analyzer/crates/project-model/src/target_data_layout.rs b/src/tools/rust-analyzer/crates/project-model/src/target_data_layout.rs
deleted file mode 100644
index 8a8a2d32558..00000000000
--- a/src/tools/rust-analyzer/crates/project-model/src/target_data_layout.rs
+++ /dev/null
@@ -1,67 +0,0 @@
-//! Runs `rustc --print target-spec-json` to get the target_data_layout.
-
-use rustc_hash::FxHashMap;
-use toolchain::Tool;
-
-use crate::{utf8_stdout, ManifestPath, Sysroot};
-
-/// Determines how `rustc --print target-spec-json` is discovered and invoked.
-pub enum RustcDataLayoutConfig<'a> {
-    /// Use `rustc --print target-spec-json`, either from with the binary from the sysroot or by discovering via
-    /// [`toolchain::rustc`].
-    Rustc(&'a Sysroot),
-    /// Use `cargo --print target-spec-json`, either from with the binary from the sysroot or by discovering via
-    /// [`toolchain::cargo`].
-    Cargo(&'a Sysroot, &'a ManifestPath),
-}
-
-pub fn get(
-    config: RustcDataLayoutConfig<'_>,
-    target: Option<&str>,
-    extra_env: &FxHashMap<String, String>,
-) -> anyhow::Result<String> {
-    let process = |output: String| {
-        (|| Some(output.split_once(r#""data-layout": ""#)?.1.split_once('"')?.0.to_owned()))()
-            .ok_or_else(|| {
-                anyhow::format_err!("could not fetch target-spec-json from command output")
-            })
-    };
-    let sysroot = match config {
-        RustcDataLayoutConfig::Cargo(sysroot, cargo_toml) => {
-            let mut cmd = sysroot.tool(Tool::Cargo);
-            cmd.envs(extra_env);
-            cmd.current_dir(cargo_toml.parent())
-                .args([
-                    "rustc",
-                    "-Z",
-                    "unstable-options",
-                    "--print",
-                    "target-spec-json",
-                    "--",
-                    "-Z",
-                    "unstable-options",
-                ])
-                .env("RUSTC_BOOTSTRAP", "1");
-            if let Some(target) = target {
-                cmd.args(["--target", target]);
-            }
-            match utf8_stdout(cmd) {
-                Ok(output) => return process(output),
-                Err(e) => {
-                    tracing::warn!("failed to run `cargo rustc --print target-spec-json`, falling back to invoking rustc directly: {e}");
-                    sysroot
-                }
-            }
-        }
-        RustcDataLayoutConfig::Rustc(sysroot) => sysroot,
-    };
-
-    let mut cmd = Sysroot::tool(sysroot, Tool::Rustc);
-    cmd.envs(extra_env)
-        .args(["-Z", "unstable-options", "--print", "target-spec-json"])
-        .env("RUSTC_BOOTSTRAP", "1");
-    if let Some(target) = target {
-        cmd.args(["--target", target]);
-    }
-    process(utf8_stdout(cmd)?)
-}
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 f3cf2d83eac..681bce3a5a6 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs
@@ -12,39 +12,44 @@ use span::FileId;
 use triomphe::Arc;
 
 use crate::{
-    sysroot::SysrootMode, workspace::ProjectWorkspaceKind, CargoWorkspace, CfgOverrides,
-    ManifestPath, ProjectJson, ProjectJsonData, ProjectWorkspace, Sysroot, SysrootQueryMetadata,
-    WorkspaceBuildScripts,
+    sysroot::SysrootWorkspace, workspace::ProjectWorkspaceKind, CargoWorkspace, CfgOverrides,
+    ManifestPath, ProjectJson, ProjectJsonData, ProjectWorkspace, Sysroot,
+    SysrootSourceWorkspaceConfig, WorkspaceBuildScripts,
 };
 
 fn load_cargo(file: &str) -> (CrateGraph, ProcMacroPaths) {
-    load_cargo_with_overrides(file, CfgOverrides::default())
+    let project_workspace = load_workspace_from_metadata(file);
+    to_crate_graph(project_workspace, &mut Default::default())
 }
 
 fn load_cargo_with_overrides(
     file: &str,
     cfg_overrides: CfgOverrides,
 ) -> (CrateGraph, ProcMacroPaths) {
+    let project_workspace =
+        ProjectWorkspace { cfg_overrides, ..load_workspace_from_metadata(file) };
+    to_crate_graph(project_workspace, &mut Default::default())
+}
+
+fn load_workspace_from_metadata(file: &str) -> ProjectWorkspace {
     let meta: Metadata = get_test_json_file(file);
     let manifest_path =
         ManifestPath::try_from(AbsPathBuf::try_from(meta.workspace_root.clone()).unwrap()).unwrap();
-    let cargo_workspace = CargoWorkspace::new(meta, manifest_path);
-    let project_workspace = ProjectWorkspace {
+    let cargo_workspace = CargoWorkspace::new(meta, manifest_path, Default::default());
+    ProjectWorkspace {
         kind: ProjectWorkspaceKind::Cargo {
             cargo: cargo_workspace,
             build_scripts: WorkspaceBuildScripts::default(),
             rustc: Err(None),
-            cargo_config_extra_env: Default::default(),
             error: None,
             set_test: true,
         },
-        cfg_overrides,
+        cfg_overrides: Default::default(),
         sysroot: Sysroot::empty(),
         rustc_cfg: Vec::new(),
         toolchain: None,
         target_layout: Err("target_data_layout not loaded".into()),
-    };
-    to_crate_graph(project_workspace)
+    }
 }
 
 fn load_rust_project(file: &str) -> (CrateGraph, ProcMacroPaths) {
@@ -59,7 +64,7 @@ fn load_rust_project(file: &str) -> (CrateGraph, ProcMacroPaths) {
         target_layout: Err(Arc::from("test has no data layout")),
         cfg_overrides: Default::default(),
     };
-    to_crate_graph(project_workspace)
+    to_crate_graph(project_workspace, &mut Default::default())
 }
 
 fn get_test_json_file<T: DeserializeOwned>(file: &str) -> T {
@@ -117,7 +122,9 @@ fn get_fake_sysroot() -> Sysroot {
     // fake sysroot, so we give them both the same path:
     let sysroot_dir = AbsPathBuf::assert(sysroot_path);
     let sysroot_src_dir = sysroot_dir.clone();
-    Sysroot::load(Some(sysroot_dir), Some(sysroot_src_dir), SysrootQueryMetadata::CargoMetadata)
+    let mut sysroot = Sysroot::new(Some(sysroot_dir), Some(sysroot_src_dir));
+    sysroot.load_workspace(&SysrootSourceWorkspaceConfig::default_cargo());
+    sysroot
 }
 
 fn rooted_project_json(data: ProjectJsonData) -> ProjectJson {
@@ -128,13 +135,15 @@ fn rooted_project_json(data: ProjectJsonData) -> ProjectJson {
     ProjectJson::new(None, base, data)
 }
 
-fn to_crate_graph(project_workspace: ProjectWorkspace) -> (CrateGraph, ProcMacroPaths) {
+fn to_crate_graph(
+    project_workspace: ProjectWorkspace,
+    file_map: &mut FxHashMap<AbsPathBuf, FileId>,
+) -> (CrateGraph, ProcMacroPaths) {
     project_workspace.to_crate_graph(
         &mut {
-            let mut counter = 0;
-            move |_path| {
-                counter += 1;
-                Some(FileId::from_raw(counter))
+            |path| {
+                let len = file_map.len() + 1;
+                Some(*file_map.entry(path.to_path_buf()).or_insert(FileId::from_raw(len as u32)))
             }
         },
         &Default::default(),
@@ -223,24 +232,50 @@ fn rust_project_is_proc_macro_has_proc_macro_dep() {
 }
 
 #[test]
+fn crate_graph_dedup_identical() {
+    let (mut crate_graph, proc_macros) = load_cargo("regex-metadata.json");
+
+    let (d_crate_graph, mut d_proc_macros) = (crate_graph.clone(), proc_macros.clone());
+
+    crate_graph.extend(d_crate_graph.clone(), &mut d_proc_macros);
+    assert!(crate_graph.iter().eq(d_crate_graph.iter()));
+    assert_eq!(proc_macros, d_proc_macros);
+}
+
+#[test]
+fn crate_graph_dedup() {
+    let mut file_map = Default::default();
+
+    let ripgrep_workspace = load_workspace_from_metadata("ripgrep-metadata.json");
+    let (mut crate_graph, _proc_macros) = to_crate_graph(ripgrep_workspace, &mut file_map);
+    assert_eq!(crate_graph.iter().count(), 71);
+
+    let regex_workspace = load_workspace_from_metadata("regex-metadata.json");
+    let (regex_crate_graph, mut regex_proc_macros) = to_crate_graph(regex_workspace, &mut file_map);
+    assert_eq!(regex_crate_graph.iter().count(), 50);
+
+    crate_graph.extend(regex_crate_graph, &mut regex_proc_macros);
+    assert_eq!(crate_graph.iter().count(), 108);
+}
+
+#[test]
 fn smoke_test_real_sysroot_cargo() {
     let file_map = &mut FxHashMap::<AbsPathBuf, FileId>::default();
     let meta: Metadata = get_test_json_file("hello-world-metadata.json");
     let manifest_path =
         ManifestPath::try_from(AbsPathBuf::try_from(meta.workspace_root.clone()).unwrap()).unwrap();
-    let cargo_workspace = CargoWorkspace::new(meta, manifest_path);
-    let sysroot = Sysroot::discover(
+    let cargo_workspace = CargoWorkspace::new(meta, manifest_path, Default::default());
+    let mut sysroot = Sysroot::discover(
         AbsPath::assert(Utf8Path::new(env!("CARGO_MANIFEST_DIR"))),
         &Default::default(),
-        SysrootQueryMetadata::CargoMetadata,
     );
-    assert!(matches!(sysroot.mode(), SysrootMode::Workspace(_)));
+    sysroot.load_workspace(&SysrootSourceWorkspaceConfig::default_cargo());
+    assert!(matches!(sysroot.workspace(), SysrootWorkspace::Workspace(_)));
     let project_workspace = ProjectWorkspace {
         kind: ProjectWorkspaceKind::Cargo {
             cargo: cargo_workspace,
             build_scripts: WorkspaceBuildScripts::default(),
             rustc: Err(None),
-            cargo_config_extra_env: Default::default(),
             error: None,
             set_test: true,
         },
diff --git a/src/tools/rust-analyzer/crates/project-model/src/toolchain_info/rustc_cfg.rs b/src/tools/rust-analyzer/crates/project-model/src/toolchain_info/rustc_cfg.rs
new file mode 100644
index 00000000000..afcc8120794
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/project-model/src/toolchain_info/rustc_cfg.rs
@@ -0,0 +1,124 @@
+//! Get the built-in cfg flags for the to be compile platform.
+
+use anyhow::Context;
+use cfg::CfgAtom;
+use rustc_hash::FxHashMap;
+use toolchain::Tool;
+
+use crate::{toolchain_info::QueryConfig, utf8_stdout};
+
+/// Uses `rustc --print cfg` to fetch the builtin cfgs.
+pub fn get(
+    config: QueryConfig<'_>,
+    target: Option<&str>,
+    extra_env: &FxHashMap<String, String>,
+) -> Vec<CfgAtom> {
+    let _p = tracing::info_span!("rustc_cfg::get").entered();
+
+    let rustc_cfgs = rustc_print_cfg(target, extra_env, config);
+    let rustc_cfgs = match rustc_cfgs {
+        Ok(cfgs) => cfgs,
+        Err(e) => {
+            tracing::error!(?e, "failed to get rustc cfgs");
+            return vec![];
+        }
+    };
+
+    // These are unstable but the standard libraries gate on them.
+    let unstable = vec![
+        r#"target_has_atomic_equal_alignment="8""#,
+        r#"target_has_atomic_equal_alignment="16""#,
+        r#"target_has_atomic_equal_alignment="32""#,
+        r#"target_has_atomic_equal_alignment="64""#,
+        r#"target_has_atomic_equal_alignment="128""#,
+        r#"target_has_atomic_equal_alignment="ptr""#,
+        r#"target_has_atomic_load_store"#,
+        r#"target_has_atomic_load_store="8""#,
+        r#"target_has_atomic_load_store="16""#,
+        r#"target_has_atomic_load_store="32""#,
+        r#"target_has_atomic_load_store="64""#,
+        r#"target_has_atomic_load_store="128""#,
+        r#"target_has_atomic_load_store="ptr""#,
+        r#"target_thread_local"#,
+        r#"target_has_atomic"#,
+    ];
+    let rustc_cfgs =
+        rustc_cfgs.lines().chain(unstable).map(crate::parse_cfg).collect::<Result<Vec<_>, _>>();
+    match rustc_cfgs {
+        Ok(rustc_cfgs) => {
+            tracing::debug!(?rustc_cfgs, "rustc cfgs found");
+            rustc_cfgs
+        }
+        Err(e) => {
+            tracing::error!(?e, "failed to parse rustc cfgs");
+            vec![]
+        }
+    }
+}
+
+fn rustc_print_cfg(
+    target: Option<&str>,
+    extra_env: &FxHashMap<String, String>,
+    config: QueryConfig<'_>,
+) -> anyhow::Result<String> {
+    const RUSTC_ARGS: [&str; 2] = ["--print", "cfg"];
+    let (sysroot, current_dir) = match config {
+        QueryConfig::Cargo(sysroot, cargo_toml) => {
+            let mut cmd = sysroot.tool(Tool::Cargo, cargo_toml.parent());
+            cmd.envs(extra_env);
+            cmd.args(["rustc"]).args(RUSTC_ARGS);
+            if let Some(target) = target {
+                cmd.args(["--target", target]);
+            }
+            cmd.args(["--", "-O"]);
+
+            match utf8_stdout(&mut cmd) {
+                Ok(it) => return Ok(it),
+                Err(e) => {
+                    tracing::warn!(
+                        %e,
+                        "failed to run `{cmd:?}`, falling back to invoking rustc directly"
+                    );
+                    (sysroot, cargo_toml.parent().as_ref())
+                }
+            }
+        }
+        QueryConfig::Rustc(sysroot, current_dir) => (sysroot, current_dir),
+    };
+
+    let mut cmd = sysroot.tool(Tool::Rustc, current_dir);
+    cmd.envs(extra_env);
+    cmd.args(RUSTC_ARGS);
+    cmd.arg("-O");
+    if let Some(target) = target {
+        cmd.args(["--target", target]);
+    }
+
+    utf8_stdout(&mut cmd).with_context(|| format!("unable to fetch cfgs via `{cmd:?}`"))
+}
+
+#[cfg(test)]
+mod tests {
+    use paths::{AbsPathBuf, Utf8PathBuf};
+
+    use crate::{ManifestPath, Sysroot};
+
+    use super::*;
+
+    #[test]
+    fn cargo() {
+        let manifest_path = concat!(env!("CARGO_MANIFEST_DIR"), "/Cargo.toml");
+        let sysroot = Sysroot::empty();
+        let manifest_path =
+            ManifestPath::try_from(AbsPathBuf::assert(Utf8PathBuf::from(manifest_path))).unwrap();
+        let cfg = QueryConfig::Cargo(&sysroot, &manifest_path);
+        assert_ne!(get(cfg, None, &FxHashMap::default()), vec![]);
+    }
+
+    #[test]
+    fn rustc() {
+        let sysroot = Sysroot::empty();
+        let cfg = QueryConfig::Rustc(&sysroot, env!("CARGO_MANIFEST_DIR").as_ref());
+        assert_ne!(get(cfg, None, &FxHashMap::default()), vec![]);
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/project-model/src/toolchain_info/target_data_layout.rs b/src/tools/rust-analyzer/crates/project-model/src/toolchain_info/target_data_layout.rs
new file mode 100644
index 00000000000..94645a91f65
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/project-model/src/toolchain_info/target_data_layout.rs
@@ -0,0 +1,83 @@
+//! Runs `rustc --print target-spec-json` to get the target_data_layout.
+
+use anyhow::Context;
+use rustc_hash::FxHashMap;
+use toolchain::Tool;
+
+use crate::{toolchain_info::QueryConfig, utf8_stdout, Sysroot};
+
+/// Uses `rustc --print target-spec-json`.
+pub fn get(
+    config: QueryConfig<'_>,
+    target: Option<&str>,
+    extra_env: &FxHashMap<String, String>,
+) -> anyhow::Result<String> {
+    const RUSTC_ARGS: [&str; 2] = ["--print", "target-spec-json"];
+    let process = |output: String| {
+        (|| Some(output.split_once(r#""data-layout": ""#)?.1.split_once('"')?.0.to_owned()))()
+            .ok_or_else(|| {
+                anyhow::format_err!("could not parse target-spec-json from command output")
+            })
+    };
+    let (sysroot, current_dir) = match config {
+        QueryConfig::Cargo(sysroot, cargo_toml) => {
+            let mut cmd = sysroot.tool(Tool::Cargo, cargo_toml.parent());
+            cmd.envs(extra_env);
+            cmd.env("RUSTC_BOOTSTRAP", "1");
+            cmd.args(["rustc", "-Z", "unstable-options"]).args(RUSTC_ARGS).args([
+                "--",
+                "-Z",
+                "unstable-options",
+            ]);
+            if let Some(target) = target {
+                cmd.args(["--target", target]);
+            }
+            match utf8_stdout(&mut cmd) {
+                Ok(output) => return process(output),
+                Err(e) => {
+                    tracing::warn!(%e, "failed to run `{cmd:?}`, falling back to invoking rustc directly");
+                    (sysroot, cargo_toml.parent().as_ref())
+                }
+            }
+        }
+        QueryConfig::Rustc(sysroot, current_dir) => (sysroot, current_dir),
+    };
+
+    let mut cmd = Sysroot::tool(sysroot, Tool::Rustc, current_dir);
+    cmd.envs(extra_env)
+        .env("RUSTC_BOOTSTRAP", "1")
+        .args(["-Z", "unstable-options"])
+        .args(RUSTC_ARGS);
+    if let Some(target) = target {
+        cmd.args(["--target", target]);
+    }
+    utf8_stdout(&mut cmd)
+        .with_context(|| format!("unable to fetch target-data-layout via `{cmd:?}`"))
+        .and_then(process)
+}
+
+#[cfg(test)]
+mod tests {
+    use paths::{AbsPathBuf, Utf8PathBuf};
+
+    use crate::{ManifestPath, Sysroot};
+
+    use super::*;
+
+    #[test]
+    fn cargo() {
+        let manifest_path = concat!(env!("CARGO_MANIFEST_DIR"), "/Cargo.toml");
+        let sysroot = Sysroot::empty();
+        let manifest_path =
+            ManifestPath::try_from(AbsPathBuf::assert(Utf8PathBuf::from(manifest_path))).unwrap();
+        let cfg = QueryConfig::Cargo(&sysroot, &manifest_path);
+        assert!(get(cfg, None, &FxHashMap::default()).is_ok());
+    }
+
+    #[test]
+    fn rustc() {
+        let sysroot = Sysroot::empty();
+        let cfg = QueryConfig::Rustc(&sysroot, env!("CARGO_MANIFEST_DIR").as_ref());
+        assert!(get(cfg, None, &FxHashMap::default()).is_ok());
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/project-model/src/toolchain_info/target_tuple.rs b/src/tools/rust-analyzer/crates/project-model/src/toolchain_info/target_tuple.rs
new file mode 100644
index 00000000000..0476de58f23
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/project-model/src/toolchain_info/target_tuple.rs
@@ -0,0 +1,105 @@
+//! Functionality to discover the current build target(s).
+use std::path::Path;
+
+use anyhow::Context;
+use rustc_hash::FxHashMap;
+use toolchain::Tool;
+
+use crate::{toolchain_info::QueryConfig, utf8_stdout, ManifestPath, Sysroot};
+
+/// For cargo, runs `cargo -Zunstable-options config get build.target` to get the configured project target(s).
+/// For rustc, runs `rustc --print -vV` to get the host target.
+pub fn get(
+    config: QueryConfig<'_>,
+    target: Option<&str>,
+    extra_env: &FxHashMap<String, String>,
+) -> anyhow::Result<Vec<String>> {
+    let _p = tracing::info_span!("target_tuple::get").entered();
+    if let Some(target) = target {
+        return Ok(vec![target.to_owned()]);
+    }
+
+    let (sysroot, current_dir) = match config {
+        QueryConfig::Cargo(sysroot, cargo_toml) => {
+            match cargo_config_build_target(cargo_toml, extra_env, sysroot) {
+                Some(it) => return Ok(it),
+                None => (sysroot, cargo_toml.parent().as_ref()),
+            }
+        }
+        QueryConfig::Rustc(sysroot, current_dir) => (sysroot, current_dir),
+    };
+    rustc_discover_host_tuple(extra_env, sysroot, current_dir).map(|it| vec![it])
+}
+
+fn rustc_discover_host_tuple(
+    extra_env: &FxHashMap<String, String>,
+    sysroot: &Sysroot,
+    current_dir: &Path,
+) -> anyhow::Result<String> {
+    let mut cmd = sysroot.tool(Tool::Rustc, current_dir);
+    cmd.envs(extra_env);
+    cmd.arg("-vV");
+    let stdout = utf8_stdout(&mut cmd)
+        .with_context(|| format!("unable to discover host platform via `{cmd:?}`"))?;
+    let field = "host: ";
+    let target = stdout.lines().find_map(|l| l.strip_prefix(field));
+    if let Some(target) = target {
+        Ok(target.to_owned())
+    } else {
+        // If we fail to resolve the host platform, it's not the end of the world.
+        Err(anyhow::format_err!("rustc -vV did not report host platform, got:\n{}", stdout))
+    }
+}
+
+fn cargo_config_build_target(
+    cargo_toml: &ManifestPath,
+    extra_env: &FxHashMap<String, String>,
+    sysroot: &Sysroot,
+) -> Option<Vec<String>> {
+    let mut cmd = sysroot.tool(Tool::Cargo, cargo_toml.parent());
+    cmd.envs(extra_env);
+    cmd.current_dir(cargo_toml.parent()).env("RUSTC_BOOTSTRAP", "1");
+    cmd.args(["-Z", "unstable-options", "config", "get", "build.target"]);
+    // if successful we receive `build.target = "target-tuple"`
+    // or `build.target = ["<target 1>", ..]`
+    // this might be `error: config value `build.target` is not set` in which case we
+    // don't wanna log the error
+    utf8_stdout(&mut cmd).and_then(parse_output_cargo_config_build_target).ok()
+}
+
+// Parses `"build.target = [target-tuple, target-tuple, ...]"` or `"build.target = "target-tuple"`
+fn parse_output_cargo_config_build_target(stdout: String) -> anyhow::Result<Vec<String>> {
+    let trimmed = stdout.trim_start_matches("build.target = ").trim_matches('"');
+
+    if !trimmed.starts_with('[') {
+        return Ok([trimmed.to_owned()].to_vec());
+    }
+
+    serde_json::from_str(trimmed).context("Failed to parse `build.target` as an array of target")
+}
+
+#[cfg(test)]
+mod tests {
+    use paths::{AbsPathBuf, Utf8PathBuf};
+
+    use crate::{ManifestPath, Sysroot};
+
+    use super::*;
+
+    #[test]
+    fn cargo() {
+        let manifest_path = concat!(env!("CARGO_MANIFEST_DIR"), "/Cargo.toml");
+        let sysroot = Sysroot::empty();
+        let manifest_path =
+            ManifestPath::try_from(AbsPathBuf::assert(Utf8PathBuf::from(manifest_path))).unwrap();
+        let cfg = QueryConfig::Cargo(&sysroot, &manifest_path);
+        assert!(get(cfg, None, &FxHashMap::default()).is_ok());
+    }
+
+    #[test]
+    fn rustc() {
+        let sysroot = Sysroot::empty();
+        let cfg = QueryConfig::Rustc(&sysroot, env!("CARGO_MANIFEST_DIR").as_ref());
+        assert!(get(cfg, None, &FxHashMap::default()).is_ok());
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/project-model/src/toolchain_info/version.rs b/src/tools/rust-analyzer/crates/project-model/src/toolchain_info/version.rs
new file mode 100644
index 00000000000..e795fdf1d64
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/project-model/src/toolchain_info/version.rs
@@ -0,0 +1,58 @@
+//! Get the version string of the toolchain.
+
+use anyhow::Context;
+use rustc_hash::FxHashMap;
+use semver::Version;
+use toolchain::Tool;
+
+use crate::{toolchain_info::QueryConfig, utf8_stdout};
+
+pub(crate) fn get(
+    config: QueryConfig<'_>,
+    extra_env: &FxHashMap<String, String>,
+) -> Result<Option<Version>, anyhow::Error> {
+    let (mut cmd, prefix) = match config {
+        QueryConfig::Cargo(sysroot, cargo_toml) => {
+            (sysroot.tool(Tool::Cargo, cargo_toml.parent()), "cargo ")
+        }
+        QueryConfig::Rustc(sysroot, current_dir) => {
+            (sysroot.tool(Tool::Rustc, current_dir), "rustc ")
+        }
+    };
+    cmd.envs(extra_env);
+    cmd.arg("--version");
+    let out = utf8_stdout(&mut cmd).with_context(|| format!("Failed to query rust toolchain version via `{cmd:?}`, is your toolchain setup correctly?"))?;
+
+    let version =
+        out.strip_prefix(prefix).and_then(|it| Version::parse(it.split_whitespace().next()?).ok());
+    if version.is_none() {
+        tracing::warn!("Failed to parse `{cmd:?}` output `{out}` as a semver version");
+    }
+    anyhow::Ok(version)
+}
+
+#[cfg(test)]
+mod tests {
+    use paths::{AbsPathBuf, Utf8PathBuf};
+
+    use crate::{ManifestPath, Sysroot};
+
+    use super::*;
+
+    #[test]
+    fn cargo() {
+        let manifest_path = concat!(env!("CARGO_MANIFEST_DIR"), "/Cargo.toml");
+        let sysroot = Sysroot::empty();
+        let manifest_path =
+            ManifestPath::try_from(AbsPathBuf::assert(Utf8PathBuf::from(manifest_path))).unwrap();
+        let cfg = QueryConfig::Cargo(&sysroot, &manifest_path);
+        assert!(get(cfg, &FxHashMap::default()).is_ok());
+    }
+
+    #[test]
+    fn rustc() {
+        let sysroot = Sysroot::empty();
+        let cfg = QueryConfig::Rustc(&sysroot, env!("CARGO_MANIFEST_DIR").as_ref());
+        assert!(get(cfg, &FxHashMap::default()).is_ok());
+    }
+}
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 71ddee30910..a345c6bcce4 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
@@ -2,7 +2,7 @@
 //! metadata` or `rust-project.json`) into representation stored in the salsa
 //! database -- `CrateGraph`.
 
-use std::{collections::VecDeque, fmt, fs, iter, sync};
+use std::{collections::VecDeque, fmt, fs, iter, ops::Deref, sync};
 
 use anyhow::Context;
 use base_db::{
@@ -16,20 +16,19 @@ use paths::{AbsPath, AbsPathBuf};
 use rustc_hash::FxHashMap;
 use semver::Version;
 use span::{Edition, FileId};
-use toolchain::Tool;
 use tracing::instrument;
 use triomphe::Arc;
 
 use crate::{
     build_dependencies::BuildScriptOutput,
-    cargo_workspace::{DepKind, PackageData, RustLibSource},
+    cargo_workspace::{CargoMetadataConfig, DepKind, PackageData, RustLibSource},
     env::{cargo_config_env, inject_cargo_env, inject_cargo_package_env, inject_rustc_tool_env},
     project_json::{Crate, CrateArrayIdx},
-    rustc_cfg::{self, RustcCfgConfig},
-    sysroot::{SysrootCrate, SysrootMode},
-    target_data_layout::{self, RustcDataLayoutConfig},
-    utf8_stdout, CargoConfig, CargoWorkspace, CfgOverrides, InvocationStrategy, ManifestPath,
-    Package, ProjectJson, ProjectManifest, Sysroot, TargetData, TargetKind, WorkspaceBuildScripts,
+    sysroot::{SysrootCrate, SysrootWorkspace},
+    toolchain_info::{rustc_cfg, target_data_layout, target_tuple, version, QueryConfig},
+    CargoConfig, CargoWorkspace, CfgOverrides, InvocationStrategy, ManifestPath, Package,
+    ProjectJson, ProjectManifest, Sysroot, SysrootSourceWorkspaceConfig, TargetData, TargetKind,
+    WorkspaceBuildScripts,
 };
 use tracing::{debug, error, info};
 
@@ -79,8 +78,6 @@ pub enum ProjectWorkspaceKind {
         /// The rustc workspace loaded for this workspace. An `Err(None)` means loading has been
         /// disabled or was otherwise not requested.
         rustc: Result<Box<(CargoWorkspace, WorkspaceBuildScripts)>, Option<String>>,
-        /// Environment variables set in the `.cargo/config` file.
-        cargo_config_extra_env: FxHashMap<String, String>,
         set_test: bool,
     },
     /// Project workspace was specified using a `rust-project.json` file.
@@ -100,8 +97,6 @@ pub enum ProjectWorkspaceKind {
         file: ManifestPath,
         /// Is this file a cargo script file?
         cargo: Option<(CargoWorkspace, WorkspaceBuildScripts, Option<Arc<anyhow::Error>>)>,
-        /// Environment variables set in the `.cargo/config` file.
-        cargo_config_extra_env: FxHashMap<String, String>,
         set_test: bool,
     },
 }
@@ -111,14 +106,7 @@ impl fmt::Debug for ProjectWorkspace {
         // Make sure this isn't too verbose.
         let Self { kind, sysroot, rustc_cfg, toolchain, target_layout, cfg_overrides } = self;
         match kind {
-            ProjectWorkspaceKind::Cargo {
-                cargo,
-                error: _,
-                build_scripts,
-                rustc,
-                cargo_config_extra_env,
-                set_test,
-            } => f
+            ProjectWorkspaceKind::Cargo { cargo, error: _, build_scripts, rustc, set_test } => f
                 .debug_struct("Cargo")
                 .field("root", &cargo.workspace_root().file_name())
                 .field("n_packages", &cargo.packages().len())
@@ -131,7 +119,6 @@ impl fmt::Debug for ProjectWorkspace {
                 .field("n_cfg_overrides", &cfg_overrides.len())
                 .field("toolchain", &toolchain)
                 .field("data_layout", &target_layout)
-                .field("cargo_config_extra_env", &cargo_config_extra_env)
                 .field("set_test", set_test)
                 .field("build_scripts", &build_scripts.error().unwrap_or("ok"))
                 .finish(),
@@ -147,12 +134,7 @@ impl fmt::Debug for ProjectWorkspace {
 
                 debug_struct.finish()
             }
-            ProjectWorkspaceKind::DetachedFile {
-                file,
-                cargo: cargo_script,
-                cargo_config_extra_env,
-                set_test,
-            } => f
+            ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script, set_test } => f
                 .debug_struct("DetachedFiles")
                 .field("file", &file)
                 .field("cargo_script", &cargo_script.is_some())
@@ -162,34 +144,12 @@ impl fmt::Debug for ProjectWorkspace {
                 .field("toolchain", &toolchain)
                 .field("data_layout", &target_layout)
                 .field("n_cfg_overrides", &cfg_overrides.len())
-                .field("cargo_config_extra_env", &cargo_config_extra_env)
                 .field("set_test", set_test)
                 .finish(),
         }
     }
 }
 
-fn get_toolchain_version(
-    current_dir: &AbsPath,
-    sysroot: &Sysroot,
-    tool: Tool,
-    extra_env: &FxHashMap<String, String>,
-    prefix: &str,
-) -> Result<Option<Version>, anyhow::Error> {
-    let cargo_version = utf8_stdout({
-        let mut cmd = Sysroot::tool(sysroot, tool);
-        cmd.envs(extra_env);
-        cmd.arg("--version").current_dir(current_dir);
-        cmd
-    })
-    .with_context(|| format!("Failed to query rust toolchain version at {current_dir}, is your toolchain setup correctly?"))?;
-    anyhow::Ok(
-        cargo_version
-            .get(prefix.len()..)
-            .and_then(|it| Version::parse(it.split_whitespace().next()?).ok()),
-    )
-}
-
 impl ProjectWorkspace {
     pub fn load(
         manifest: ProjectManifest,
@@ -220,167 +180,159 @@ impl ProjectWorkspace {
                 ProjectWorkspace::load_detached_file(rust_file, config)?
             }
             ProjectManifest::CargoToml(cargo_toml) => {
-                let sysroot = match (&config.sysroot, &config.sysroot_src) {
-                    (Some(RustLibSource::Discover), None) => Sysroot::discover(
-                        cargo_toml.parent(),
-                        &config.extra_env,
-                        config.sysroot_query_metadata,
-                    ),
-                    (Some(RustLibSource::Discover), Some(sysroot_src)) => {
-                        Sysroot::discover_with_src_override(
-                            cargo_toml.parent(),
-                            &config.extra_env,
-                            sysroot_src.clone(),
-                            config.sysroot_query_metadata,
-                        )
-                    }
-                    (Some(RustLibSource::Path(path)), None) => Sysroot::discover_sysroot_src_dir(
-                        path.clone(),
-                        config.sysroot_query_metadata,
-                    ),
-                    (Some(RustLibSource::Path(sysroot)), Some(sysroot_src)) => Sysroot::load(
-                        Some(sysroot.clone()),
-                        Some(sysroot_src.clone()),
-                        config.sysroot_query_metadata,
-                    ),
-                    (None, _) => Sysroot::empty(),
-                };
-                tracing::info!(workspace = %cargo_toml, src_root = ?sysroot.src_root(), root = ?sysroot.root(), "Using sysroot");
-
-                let rustc_dir = match &config.rustc_source {
-                    Some(RustLibSource::Path(path)) => ManifestPath::try_from(path.clone())
-                        .map_err(|p| Some(format!("rustc source path is not absolute: {p}"))),
-                    Some(RustLibSource::Discover) => {
-                        sysroot.discover_rustc_src().ok_or_else(|| {
-                            Some("Failed to discover rustc source for sysroot.".to_owned())
-                        })
-                    }
-                    None => Err(None),
-                };
+                ProjectWorkspace::load_cargo(cargo_toml, config, progress)?
+            }
+        };
 
-                let rustc =  rustc_dir.and_then(|rustc_dir| {
-                    info!(workspace = %cargo_toml, rustc_dir = %rustc_dir, "Using rustc source");
-                    match CargoWorkspace::fetch_metadata(
-                        &rustc_dir,
-                        cargo_toml.parent(),
-                        &CargoConfig {
-                            features: crate::CargoFeatures::default(),
-                            ..config.clone()
-                        },
-                        &sysroot,
-                        false,
-                        progress,
-                    ) {
-                        Ok((meta, _error)) => {
-                            let workspace = CargoWorkspace::new(meta, cargo_toml.clone());
-                            let buildscripts = WorkspaceBuildScripts::rustc_crates(
-                                &workspace,
-                                cargo_toml.parent(),
-                                &config.extra_env,
-                                &sysroot
-                            );
-                            Ok(Box::new((workspace, buildscripts)))
-                        }
-                        Err(e) => {
-                            tracing::error!(
-                                %e,
-                                "Failed to read Cargo metadata from rustc source at {rustc_dir}",
-                            );
-                            Err(Some(format!(
-                                "Failed to read Cargo metadata from rustc source at {rustc_dir}: {e}"
-                            )))
-                        }
-                    }
-                });
+        Ok(res)
+    }
 
-                let toolchain = get_toolchain_version(
+    fn load_cargo(
+        cargo_toml: &ManifestPath,
+        config: &CargoConfig,
+        progress: &dyn Fn(String),
+    ) -> Result<ProjectWorkspace, anyhow::Error> {
+        let mut sysroot = match (&config.sysroot, &config.sysroot_src) {
+            (Some(RustLibSource::Discover), None) => {
+                Sysroot::discover(cargo_toml.parent(), &config.extra_env)
+            }
+            (Some(RustLibSource::Discover), Some(sysroot_src)) => {
+                Sysroot::discover_with_src_override(
                     cargo_toml.parent(),
-                    &sysroot,
-                    Tool::Cargo,
                     &config.extra_env,
-                    "cargo ",
-                )?;
-                let rustc_cfg = rustc_cfg::get(
-                    config.target.as_deref(),
-                    &config.extra_env,
-                    RustcCfgConfig::Cargo(&sysroot, cargo_toml),
-                );
+                    sysroot_src.clone(),
+                )
+            }
+            (Some(RustLibSource::Path(path)), None) => {
+                Sysroot::discover_sysroot_src_dir(path.clone())
+            }
+            (Some(RustLibSource::Path(sysroot)), Some(sysroot_src)) => {
+                Sysroot::new(Some(sysroot.clone()), Some(sysroot_src.clone()))
+            }
+            (None, _) => Sysroot::empty(),
+        };
 
-                let cfg_overrides = config.cfg_overrides.clone();
-                let data_layout = target_data_layout::get(
-                    RustcDataLayoutConfig::Cargo(&sysroot, cargo_toml),
-                    config.target.as_deref(),
-                    &config.extra_env,
-                );
-                if let Err(e) = &data_layout {
-                    tracing::error!(%e, "failed fetching data layout for {cargo_toml:?} workspace");
-                }
+        let rustc_dir = match &config.rustc_source {
+            Some(RustLibSource::Path(path)) => ManifestPath::try_from(path.clone())
+                .map_err(|p| Some(format!("rustc source path is not absolute: {p}"))),
+            Some(RustLibSource::Discover) => sysroot
+                .discover_rustc_src()
+                .ok_or_else(|| Some("Failed to discover rustc source for sysroot.".to_owned())),
+            None => Err(None),
+        };
 
-                let (meta, error) = CargoWorkspace::fetch_metadata(
-                    cargo_toml,
-                    cargo_toml.parent(),
-                    config,
-                    &sysroot,
-                        false,
-                        progress,
+        tracing::info!(workspace = %cargo_toml, src_root = ?sysroot.src_root(), root = ?sysroot.root(), "Using sysroot");
+        let toolchain_config = QueryConfig::Cargo(&sysroot, cargo_toml);
+        let targets =
+            target_tuple::get(toolchain_config, config.target.as_deref(), &config.extra_env)
+                .unwrap_or_default();
+        let toolchain = version::get(toolchain_config, &config.extra_env)
+            .inspect_err(|e| {
+                tracing::error!(%e,
+                    "failed fetching toolchain version for {cargo_toml:?} workspace"
                 )
-                .with_context(|| {
-                    format!(
-                        "Failed to read Cargo metadata from Cargo.toml file {cargo_toml}, {toolchain:?}",
-                    )
-                })?;
-                let cargo = CargoWorkspace::new(meta, cargo_toml.clone());
-
-                let cargo_config_extra_env =
-                    cargo_config_env(cargo_toml, &config.extra_env, &sysroot);
-                ProjectWorkspace {
-                    kind: ProjectWorkspaceKind::Cargo {
-                        cargo,
-                        build_scripts: WorkspaceBuildScripts::default(),
-                        rustc,
-                        cargo_config_extra_env,
-                        error: error.map(Arc::new),
-                        set_test: config.set_test,
-                    },
-                    sysroot,
-                    rustc_cfg,
-                    cfg_overrides,
-                    toolchain,
-                    target_layout: data_layout
-                        .map(Arc::from)
-                        .map_err(|it| Arc::from(it.to_string())),
+            })
+            .ok()
+            .flatten();
+        let rustc_cfg =
+            rustc_cfg::get(toolchain_config, targets.first().map(Deref::deref), &config.extra_env);
+        let cfg_overrides = config.cfg_overrides.clone();
+        let data_layout = target_data_layout::get(
+            toolchain_config,
+            targets.first().map(Deref::deref),
+            &config.extra_env,
+        );
+        if let Err(e) = &data_layout {
+            tracing::error!(%e, "failed fetching data layout for {cargo_toml:?} workspace");
+        }
+        sysroot.load_workspace(&SysrootSourceWorkspaceConfig::CargoMetadata(
+            sysroot_metadata_config(&config.extra_env, &targets),
+        ));
+
+        let rustc = rustc_dir.and_then(|rustc_dir| {
+            info!(workspace = %cargo_toml, rustc_dir = %rustc_dir, "Using rustc source");
+            match CargoWorkspace::fetch_metadata(
+                &rustc_dir,
+                cargo_toml.parent(),
+                &CargoMetadataConfig {
+                    features: crate::CargoFeatures::default(),
+                    targets: targets.clone(),
+                    extra_args: config.extra_args.clone(),
+                    extra_env: config.extra_env.clone(),
+                },
+                &sysroot,
+                false,
+                progress,
+            ) {
+                Ok((meta, _error)) => {
+                    let workspace = CargoWorkspace::new(meta, cargo_toml.clone(), Env::default());
+                    let build_scripts = WorkspaceBuildScripts::rustc_crates(
+                        &workspace,
+                        cargo_toml.parent(),
+                        &config.extra_env,
+                        &sysroot,
+                    );
+                    Ok(Box::new((workspace, build_scripts)))
+                }
+                Err(e) => {
+                    tracing::error!(
+                        %e,
+                        "Failed to read Cargo metadata from rustc source at {rustc_dir}",
+                    );
+                    Err(Some(format!(
+                        "Failed to read Cargo metadata from rustc source at {rustc_dir}: {e}"
+                    )))
                 }
             }
-        };
+        });
+
+        let (meta, error) = CargoWorkspace::fetch_metadata(
+            cargo_toml,
+            cargo_toml.parent(),
+            &CargoMetadataConfig {
+                features: config.features.clone(),
+                targets,
+                extra_args: config.extra_args.clone(),
+                extra_env: config.extra_env.clone(),
+            },
+            &sysroot,
+            false,
+            progress,
+        )
+        .with_context(|| {
+            format!(
+                "Failed to read Cargo metadata from Cargo.toml file {cargo_toml}, {toolchain:?}",
+            )
+        })?;
+        let cargo_config_extra_env = cargo_config_env(cargo_toml, &config.extra_env, &sysroot);
+        let cargo = CargoWorkspace::new(meta, cargo_toml.clone(), cargo_config_extra_env);
 
-        Ok(res)
+        Ok(ProjectWorkspace {
+            kind: ProjectWorkspaceKind::Cargo {
+                cargo,
+                build_scripts: WorkspaceBuildScripts::default(),
+                rustc,
+                error: error.map(Arc::new),
+                set_test: config.set_test,
+            },
+            sysroot,
+            rustc_cfg,
+            cfg_overrides,
+            toolchain,
+            target_layout: data_layout.map(Arc::from).map_err(|it| Arc::from(it.to_string())),
+        })
     }
 
     pub fn load_inline(project_json: ProjectJson, config: &CargoConfig) -> ProjectWorkspace {
-        let sysroot = Sysroot::load(
-            project_json.sysroot.clone(),
-            project_json.sysroot_src.clone(),
-            config.sysroot_query_metadata,
-        );
-        let cfg_config = RustcCfgConfig::Rustc(&sysroot);
-        let data_layout_config = RustcDataLayoutConfig::Rustc(&sysroot);
-        let toolchain = match get_toolchain_version(
-            project_json.path(),
-            &sysroot,
-            Tool::Rustc,
-            &config.extra_env,
-            "rustc ",
-        ) {
-            Ok(it) => it,
-            Err(e) => {
-                tracing::error!("{e}");
-                None
-            }
-        };
+        let mut sysroot =
+            Sysroot::new(project_json.sysroot.clone(), project_json.sysroot_src.clone());
+        sysroot.load_workspace(&SysrootSourceWorkspaceConfig::Stitched);
+        let query_config = QueryConfig::Rustc(&sysroot, project_json.path().as_ref());
+        let toolchain = version::get(query_config, &config.extra_env).ok().flatten();
 
         let target = config.target.as_deref();
-        let rustc_cfg = rustc_cfg::get(target, &config.extra_env, cfg_config);
-        let data_layout = target_data_layout::get(data_layout_config, target, &config.extra_env);
+        let rustc_cfg = rustc_cfg::get(query_config, target, &config.extra_env);
+        let data_layout = target_data_layout::get(query_config, target, &config.extra_env);
         ProjectWorkspace {
             kind: ProjectWorkspaceKind::Json(project_json),
             sysroot,
@@ -396,49 +348,50 @@ impl ProjectWorkspace {
         config: &CargoConfig,
     ) -> anyhow::Result<ProjectWorkspace> {
         let dir = detached_file.parent();
-        let sysroot = match &config.sysroot {
-            Some(RustLibSource::Path(path)) => {
-                Sysroot::discover_sysroot_src_dir(path.clone(), config.sysroot_query_metadata)
-            }
-            Some(RustLibSource::Discover) => {
-                Sysroot::discover(dir, &config.extra_env, config.sysroot_query_metadata)
-            }
+        let mut sysroot = match &config.sysroot {
+            Some(RustLibSource::Path(path)) => Sysroot::discover_sysroot_src_dir(path.clone()),
+            Some(RustLibSource::Discover) => Sysroot::discover(dir, &config.extra_env),
             None => Sysroot::empty(),
         };
 
-        let toolchain =
-            match get_toolchain_version(dir, &sysroot, Tool::Rustc, &config.extra_env, "rustc ") {
-                Ok(it) => it,
-                Err(e) => {
-                    tracing::error!("{e}");
-                    None
-                }
-            };
-
-        let rustc_cfg = rustc_cfg::get(None, &config.extra_env, RustcCfgConfig::Rustc(&sysroot));
-        let data_layout = target_data_layout::get(
-            RustcDataLayoutConfig::Rustc(&sysroot),
-            None,
-            &config.extra_env,
-        );
-
-        let cargo_script =
-            CargoWorkspace::fetch_metadata(detached_file, dir, config, &sysroot, false, &|_| ())
-                .ok()
-                .map(|(ws, error)| {
-                    (
-                        CargoWorkspace::new(ws, detached_file.clone()),
-                        WorkspaceBuildScripts::default(),
-                        error.map(Arc::new),
-                    )
-                });
+        let query_config = QueryConfig::Cargo(&sysroot, detached_file);
+        let toolchain = version::get(query_config, &config.extra_env).ok().flatten();
+        let targets = target_tuple::get(query_config, config.target.as_deref(), &config.extra_env)
+            .unwrap_or_default();
+        let rustc_cfg = rustc_cfg::get(query_config, None, &config.extra_env);
+        let data_layout = target_data_layout::get(query_config, None, &config.extra_env);
+        sysroot.load_workspace(&SysrootSourceWorkspaceConfig::CargoMetadata(
+            sysroot_metadata_config(&config.extra_env, &targets),
+        ));
+
+        let cargo_script = CargoWorkspace::fetch_metadata(
+            detached_file,
+            dir,
+            &CargoMetadataConfig {
+                features: config.features.clone(),
+                targets,
+                extra_args: config.extra_args.clone(),
+                extra_env: config.extra_env.clone(),
+            },
+            &sysroot,
+            false,
+            &|_| (),
+        )
+        .ok()
+        .map(|(ws, error)| {
+            let cargo_config_extra_env =
+                cargo_config_env(detached_file, &config.extra_env, &sysroot);
+            (
+                CargoWorkspace::new(ws, detached_file.clone(), cargo_config_extra_env),
+                WorkspaceBuildScripts::default(),
+                error.map(Arc::new),
+            )
+        });
 
-        let cargo_config_extra_env = cargo_config_env(detached_file, &config.extra_env, &sysroot);
         Ok(ProjectWorkspace {
             kind: ProjectWorkspaceKind::DetachedFile {
                 file: detached_file.to_owned(),
                 cargo: cargo_script,
-                cargo_config_extra_env,
                 set_test: config.set_test,
             },
             sysroot,
@@ -565,8 +518,8 @@ impl ProjectWorkspace {
     /// the root is a member of the current workspace
     pub fn to_roots(&self) -> Vec<PackageRoot> {
         let mk_sysroot = || {
-            let mut r = match self.sysroot.mode() {
-                SysrootMode::Workspace(ws) => ws
+            let mut r = match self.sysroot.workspace() {
+                SysrootWorkspace::Workspace(ws) => ws
                     .packages()
                     .filter_map(|pkg| {
                         if ws[pkg].is_local {
@@ -587,7 +540,7 @@ impl ProjectWorkspace {
                         Some(PackageRoot { is_local: false, include, exclude })
                     })
                     .collect(),
-                SysrootMode::Stitched(_) | SysrootMode::Empty => vec![],
+                SysrootWorkspace::Stitched(_) | SysrootWorkspace::Empty => vec![],
             };
 
             r.push(PackageRoot {
@@ -601,32 +554,25 @@ impl ProjectWorkspace {
             ProjectWorkspaceKind::Json(project) => project
                 .crates()
                 .map(|(_, krate)| {
-                    let build_files = project
-                        .crates()
-                        .filter_map(|(_, krate)| {
-                            krate.build.as_ref().map(|build| build.build_file.clone())
-                        })
-                        // FIXME: PackageRoots dont allow specifying files, only directories
-                        .filter_map(|build_file| {
-                            self.workspace_root().join(build_file).parent().map(ToOwned::to_owned)
-                        });
+                    // FIXME: PackageRoots dont allow specifying files, only directories
+                    let build_file = krate
+                        .build
+                        .as_ref()
+                        .map(|build| self.workspace_root().join(&build.build_file))
+                        .as_deref()
+                        .and_then(AbsPath::parent)
+                        .map(ToOwned::to_owned);
+
                     PackageRoot {
                         is_local: krate.is_workspace_member,
-                        include: krate.include.iter().cloned().chain(build_files).collect(),
+                        include: krate.include.iter().cloned().chain(build_file).collect(),
                         exclude: krate.exclude.clone(),
                     }
                 })
                 .chain(mk_sysroot())
                 .unique()
                 .collect(),
-            ProjectWorkspaceKind::Cargo {
-                cargo,
-                rustc,
-                build_scripts,
-                cargo_config_extra_env: _,
-                error: _,
-                set_test: _,
-            } => {
+            ProjectWorkspaceKind::Cargo { cargo, rustc, build_scripts, error: _, set_test: _ } => {
                 cargo
                     .packages()
                     .map(|pkg| {
@@ -763,23 +709,18 @@ impl ProjectWorkspace {
                 extra_env,
                 cfg_overrides,
             ),
-            ProjectWorkspaceKind::Cargo {
-                cargo,
-                rustc,
-                build_scripts,
-                cargo_config_extra_env: _,
-                error: _,
-                set_test,
-            } => cargo_to_crate_graph(
-                load,
-                rustc.as_ref().map(|a| a.as_ref()).ok(),
-                cargo,
-                sysroot,
-                rustc_cfg.clone(),
-                cfg_overrides,
-                build_scripts,
-                *set_test,
-            ),
+            ProjectWorkspaceKind::Cargo { cargo, rustc, build_scripts, error: _, set_test } => {
+                cargo_to_crate_graph(
+                    load,
+                    rustc.as_ref().map(|a| a.as_ref()).ok(),
+                    cargo,
+                    sysroot,
+                    rustc_cfg.clone(),
+                    cfg_overrides,
+                    build_scripts,
+                    *set_test,
+                )
+            }
             ProjectWorkspaceKind::DetachedFile { file, cargo: cargo_script, set_test, .. } => {
                 if let Some((cargo, build_scripts, _)) = cargo_script {
                     cargo_to_crate_graph(
@@ -824,7 +765,6 @@ impl ProjectWorkspace {
                 ProjectWorkspaceKind::Cargo {
                     cargo,
                     rustc,
-                    cargo_config_extra_env,
                     build_scripts: _,
                     error: _,
                     set_test: _,
@@ -832,16 +772,11 @@ impl ProjectWorkspace {
                 ProjectWorkspaceKind::Cargo {
                     cargo: o_cargo,
                     rustc: o_rustc,
-                    cargo_config_extra_env: o_cargo_config_extra_env,
                     build_scripts: _,
                     error: _,
                     set_test: _,
                 },
-            ) => {
-                cargo == o_cargo
-                    && rustc == o_rustc
-                    && cargo_config_extra_env == o_cargo_config_extra_env
-            }
+            ) => cargo == o_cargo && rustc == o_rustc,
             (ProjectWorkspaceKind::Json(project), ProjectWorkspaceKind::Json(o_project)) => {
                 project == o_project
             }
@@ -849,20 +784,14 @@ impl ProjectWorkspace {
                 ProjectWorkspaceKind::DetachedFile {
                     file,
                     cargo: Some((cargo_script, _, _)),
-                    cargo_config_extra_env,
                     set_test: _,
                 },
                 ProjectWorkspaceKind::DetachedFile {
                     file: o_file,
                     cargo: Some((o_cargo_script, _, _)),
-                    cargo_config_extra_env: o_cargo_config_extra_env,
                     set_test: _,
                 },
-            ) => {
-                file == o_file
-                    && cargo_script == o_cargo_script
-                    && cargo_config_extra_env == o_cargo_config_extra_env
-            }
+            ) => file == o_file && cargo_script == o_cargo_script,
             _ => return false,
         }) && sysroot == o_sysroot
             && rustc_cfg == o_rustc_cfg
@@ -921,7 +850,11 @@ fn project_json_to_crate_graph(
 
                 let target_cfgs = match target.as_deref() {
                     Some(target) => cfg_cache.entry(target).or_insert_with(|| {
-                        rustc_cfg::get(Some(target), extra_env, RustcCfgConfig::Rustc(sysroot))
+                        rustc_cfg::get(
+                            QueryConfig::Rustc(sysroot, project.project_root().as_ref()),
+                            Some(target),
+                            extra_env,
+                        )
                     }),
                     None => &rustc_cfg,
                 };
@@ -1374,15 +1307,13 @@ fn add_target_crate_root(
         opts
     };
 
-    let mut env = Env::default();
+    let mut env = cargo.env().clone();
     inject_cargo_package_env(&mut env, pkg);
     inject_cargo_env(&mut env);
-    inject_rustc_tool_env(&mut env, cargo, cargo_name, kind);
+    inject_rustc_tool_env(&mut env, cargo_name, kind);
 
     if let Some(envs) = build_data.map(|(it, _)| &it.envs) {
-        for (k, v) in envs {
-            env.set(k, v.clone());
-        }
+        env.extend_from_other(envs);
     }
     let crate_id = crate_graph.add_crate_root(
         file_id,
@@ -1433,8 +1364,8 @@ fn sysroot_to_crate_graph(
     load: FileLoader<'_>,
 ) -> (SysrootPublicDeps, Option<CrateId>) {
     let _p = tracing::info_span!("sysroot_to_crate_graph").entered();
-    match sysroot.mode() {
-        SysrootMode::Workspace(cargo) => {
+    match sysroot.workspace() {
+        SysrootWorkspace::Workspace(cargo) => {
             let (mut cg, mut pm) = cargo_to_crate_graph(
                 load,
                 None,
@@ -1509,7 +1440,7 @@ fn sysroot_to_crate_graph(
 
             (SysrootPublicDeps { deps: pub_deps }, libproc_macro)
         }
-        SysrootMode::Stitched(stitched) => {
+        SysrootWorkspace::Stitched(stitched) => {
             let cfg_options = Arc::new({
                 let mut cfg_options = CfgOptions::default();
                 cfg_options.extend(rustc_cfg);
@@ -1562,7 +1493,7 @@ fn sysroot_to_crate_graph(
                 stitched.proc_macro().and_then(|it| sysroot_crates.get(&it).copied());
             (public_deps, libproc_macro)
         }
-        SysrootMode::Empty => (SysrootPublicDeps { deps: vec![] }, None),
+        SysrootWorkspace::Empty => (SysrootPublicDeps { deps: vec![] }, None),
     }
 }
 
@@ -1597,3 +1528,15 @@ fn add_dep_inner(graph: &mut CrateGraph, from: CrateId, dep: Dependency) {
         tracing::warn!("{}", err)
     }
 }
+
+fn sysroot_metadata_config(
+    extra_env: &FxHashMap<String, String>,
+    targets: &[String],
+) -> CargoMetadataConfig {
+    CargoMetadataConfig {
+        features: Default::default(),
+        targets: targets.to_vec(),
+        extra_args: Default::default(),
+        extra_env: extra_env.clone(),
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt
index 90f41a9c2fc..2026ab2b8c2 100644
--- a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt
+++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt
@@ -479,7 +479,7 @@
     },
     11: CrateData {
         root_file_id: FileId(
-            12,
+            11,
         ),
         edition: Edition2018,
         version: None,
diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/regex-metadata.json b/src/tools/rust-analyzer/crates/project-model/test_data/regex-metadata.json
new file mode 100644
index 00000000000..371464dd20a
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/project-model/test_data/regex-metadata.json
@@ -0,0 +1,6420 @@
+{
+    "packages": [
+        {
+            "name": "aho-corasick",
+            "version": "0.7.20",
+            "id": "aho-corasick 0.7.20 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "Unlicense OR MIT",
+            "license_file": null,
+            "description": "Fast multiple substring searching.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "memchr",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^2.4.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "aho_corasick",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/aho-corasick-0.7.20/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                }
+            ],
+            "features": {
+                "default": [
+                    "std"
+                ],
+                "std": [
+                    "memchr/std"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/aho-corasick-0.7.20/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>"
+            ],
+            "categories": [
+                "text-processing"
+            ],
+            "keywords": [
+                "string",
+                "search",
+                "text",
+                "aho",
+                "multi"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/BurntSushi/aho-corasick",
+            "homepage": "https://github.com/BurntSushi/aho-corasick",
+            "documentation": null,
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "cc",
+            "version": "1.0.79",
+            "id": "cc 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "A build-time dependency for Cargo build scripts to assist in invoking the native\nC compiler to compile native C code into a static archive to be linked into Rust\ncode.\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "jobserver",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1.16",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "tempfile",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^3",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "cc",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/cc-1.0.79/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bin"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "gcc-shim",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/cc-1.0.79/src/bin/gcc-shim.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "cc_env",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/cc-1.0.79/tests/cc_env.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "cflags",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/cc-1.0.79/tests/cflags.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "cxxflags",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/cc-1.0.79/tests/cxxflags.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/cc-1.0.79/tests/test.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                }
+            ],
+            "features": {
+                "jobserver": [
+                    "dep:jobserver"
+                ],
+                "parallel": [
+                    "jobserver"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/cc-1.0.79/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Alex Crichton <alex@alexcrichton.com>"
+            ],
+            "categories": [
+                "development-tools::build-utils"
+            ],
+            "keywords": [
+                "build-dependencies"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/rust-lang/cc-rs",
+            "homepage": "https://github.com/rust-lang/cc-rs",
+            "documentation": "https://docs.rs/cc",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "cfg-if",
+            "version": "0.1.10",
+            "id": "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT/Apache-2.0",
+            "license_file": null,
+            "description": "A macro to ergonomically define an item depending on a large number of #[cfg]\nparameters. Structured like an if-else chain, the first matching branch is the\nitem that gets emitted.\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "compiler_builtins",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1.2",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rustc-std-workspace-core",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.0",
+                    "kind": null,
+                    "rename": "core",
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "cfg-if",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/cfg-if-0.1.10/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "xcrate",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/cfg-if-0.1.10/tests/xcrate.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                }
+            ],
+            "features": {
+                "compiler_builtins": [
+                    "dep:compiler_builtins"
+                ],
+                "core": [
+                    "dep:core"
+                ],
+                "rustc-dep-of-std": [
+                    "core",
+                    "compiler_builtins"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/cfg-if-0.1.10/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Alex Crichton <alex@alexcrichton.com>"
+            ],
+            "categories": [],
+            "keywords": [],
+            "readme": "README.md",
+            "repository": "https://github.com/alexcrichton/cfg-if",
+            "homepage": "https://github.com/alexcrichton/cfg-if",
+            "documentation": "https://docs.rs/cfg-if",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "cfg-if",
+            "version": "1.0.0",
+            "id": "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT/Apache-2.0",
+            "license_file": null,
+            "description": "A macro to ergonomically define an item depending on a large number of #[cfg]\nparameters. Structured like an if-else chain, the first matching branch is the\nitem that gets emitted.\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "compiler_builtins",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1.2",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rustc-std-workspace-core",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.0",
+                    "kind": null,
+                    "rename": "core",
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "cfg-if",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/cfg-if-1.0.0/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "xcrate",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/cfg-if-1.0.0/tests/xcrate.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                }
+            ],
+            "features": {
+                "compiler_builtins": [
+                    "dep:compiler_builtins"
+                ],
+                "core": [
+                    "dep:core"
+                ],
+                "rustc-dep-of-std": [
+                    "core",
+                    "compiler_builtins"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/cfg-if-1.0.0/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Alex Crichton <alex@alexcrichton.com>"
+            ],
+            "categories": [],
+            "keywords": [],
+            "readme": "README.md",
+            "repository": "https://github.com/alexcrichton/cfg-if",
+            "homepage": "https://github.com/alexcrichton/cfg-if",
+            "documentation": "https://docs.rs/cfg-if",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "docopt",
+            "version": "1.1.1",
+            "id": "docopt 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "Unlicense/MIT",
+            "license_file": null,
+            "description": "Command line argument parsing.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "lazy_static",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.3",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "regex",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.4.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [
+                        "std",
+                        "unicode"
+                    ],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [
+                        "derive"
+                    ],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "strsim",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.10",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "docopt",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/docopt-1.1.1/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bin"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "docopt-wordlist",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/docopt-1.1.1/src/wordlist.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "cargo",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/docopt-1.1.1/examples/cargo.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "cp",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/docopt-1.1.1/examples/cp.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "decode",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/docopt-1.1.1/examples/decode.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "hashmap",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/docopt-1.1.1/examples/hashmap.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "optional_command",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/docopt-1.1.1/examples/optional_command.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "verbose_multiple",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/docopt-1.1.1/examples/verbose_multiple.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/docopt-1.1.1/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>"
+            ],
+            "categories": [
+                "command-line-interface"
+            ],
+            "keywords": [
+                "docopt",
+                "argument",
+                "command",
+                "argv"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/docopt/docopt.rs",
+            "homepage": "https://github.com/docopt/docopt.rs",
+            "documentation": "http://burntsushi.net/rustdoc/docopt/",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "getrandom",
+            "version": "0.2.9",
+            "id": "getrandom 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "A small cross-platform library for retrieving random data from system source",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "cfg-if",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "compiler_builtins",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rustc-std-workspace-core",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": null,
+                    "rename": "core",
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "js-sys",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": "cfg(all(any(target_arch = \"wasm32\", target_arch = \"wasm64\"), target_os = \"unknown\"))",
+                    "registry": null
+                },
+                {
+                    "name": "wasm-bindgen",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2.62",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": "cfg(all(any(target_arch = \"wasm32\", target_arch = \"wasm64\"), target_os = \"unknown\"))",
+                    "registry": null
+                },
+                {
+                    "name": "wasm-bindgen-test",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3.18",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": "cfg(all(any(target_arch = \"wasm32\", target_arch = \"wasm64\"), target_os = \"unknown\"))",
+                    "registry": null
+                },
+                {
+                    "name": "wasi",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.11",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": "cfg(target_os = \"wasi\")",
+                    "registry": null
+                },
+                {
+                    "name": "libc",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2.139",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": "cfg(unix)",
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "getrandom",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/getrandom-0.2.9/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "custom",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/getrandom-0.2.9/tests/custom.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "normal",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/getrandom-0.2.9/tests/normal.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "rdrand",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/getrandom-0.2.9/tests/rdrand.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bench"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "buffer",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/getrandom-0.2.9/benches/buffer.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "compiler_builtins": [
+                    "dep:compiler_builtins"
+                ],
+                "core": [
+                    "dep:core"
+                ],
+                "custom": [],
+                "js": [
+                    "wasm-bindgen",
+                    "js-sys"
+                ],
+                "js-sys": [
+                    "dep:js-sys"
+                ],
+                "rdrand": [],
+                "rustc-dep-of-std": [
+                    "compiler_builtins",
+                    "core",
+                    "libc/rustc-dep-of-std",
+                    "wasi/rustc-dep-of-std"
+                ],
+                "std": [],
+                "test-in-browser": [],
+                "wasm-bindgen": [
+                    "dep:wasm-bindgen"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/getrandom-0.2.9/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "features": [
+                            "std",
+                            "custom"
+                        ],
+                        "rustdoc-args": [
+                            "--cfg",
+                            "docsrs"
+                        ]
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "The Rand Project Developers"
+            ],
+            "categories": [
+                "os",
+                "no-std"
+            ],
+            "keywords": [],
+            "readme": "README.md",
+            "repository": "https://github.com/rust-random/getrandom",
+            "homepage": null,
+            "documentation": "https://docs.rs/getrandom",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "lazy_static",
+            "version": "1.4.0",
+            "id": "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT/Apache-2.0",
+            "license_file": null,
+            "description": "A macro for declaring lazily evaluated statics in Rust.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "spin",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.5.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "doc-comment",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3.1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "lazy_static",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/lazy_static-1.4.0/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "no_std",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/lazy_static-1.4.0/tests/no_std.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/lazy_static-1.4.0/tests/test.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                }
+            ],
+            "features": {
+                "spin": [
+                    "dep:spin"
+                ],
+                "spin_no_std": [
+                    "spin"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/lazy_static-1.4.0/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Marvin Löbel <loebel.marvin@gmail.com>"
+            ],
+            "categories": [
+                "no-std",
+                "rust-patterns",
+                "memory-management"
+            ],
+            "keywords": [
+                "macro",
+                "lazy",
+                "static"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/rust-lang-nursery/lazy-static.rs",
+            "homepage": null,
+            "documentation": "https://docs.rs/lazy_static",
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "libc",
+            "version": "0.2.142",
+            "id": "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "Raw FFI bindings to platform libraries like libc.\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "rustc-std-workspace-core",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "libc",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/libc-0.2.142/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "const_fn",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/libc-0.2.142/tests/const_fn.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "custom-build"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "build-script-build",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/libc-0.2.142/build.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "align": [],
+                "const-extern-fn": [],
+                "default": [
+                    "std"
+                ],
+                "extra_traits": [],
+                "rustc-dep-of-std": [
+                    "align",
+                    "rustc-std-workspace-core"
+                ],
+                "rustc-std-workspace-core": [
+                    "dep:rustc-std-workspace-core"
+                ],
+                "std": [],
+                "use_std": [
+                    "std"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/libc-0.2.142/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "features": [
+                            "const-extern-fn",
+                            "extra_traits"
+                        ]
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "The Rust Project Developers"
+            ],
+            "categories": [
+                "external-ffi-bindings",
+                "no-std",
+                "os"
+            ],
+            "keywords": [
+                "libc",
+                "ffi",
+                "bindings",
+                "operating",
+                "system"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/rust-lang/libc",
+            "homepage": "https://github.com/rust-lang/libc",
+            "documentation": "https://docs.rs/libc/",
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "memchr",
+            "version": "2.5.0",
+            "id": "memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "Unlicense/MIT",
+            "license_file": null,
+            "description": "Safe interface to memchr.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "compiler_builtins",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1.2",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rustc-std-workspace-core",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.0",
+                    "kind": null,
+                    "rename": "core",
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "libc",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2.18",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "quickcheck",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.3",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "memchr",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/memchr-2.5.0/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "custom-build"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "build-script-build",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/memchr-2.5.0/build.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "compiler_builtins": [
+                    "dep:compiler_builtins"
+                ],
+                "core": [
+                    "dep:core"
+                ],
+                "default": [
+                    "std"
+                ],
+                "libc": [
+                    "dep:libc"
+                ],
+                "rustc-dep-of-std": [
+                    "core",
+                    "compiler_builtins"
+                ],
+                "std": [],
+                "use_std": [
+                    "std"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/memchr-2.5.0/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>",
+                "bluss"
+            ],
+            "categories": [],
+            "keywords": [
+                "memchr",
+                "char",
+                "scan",
+                "strchr",
+                "string"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/BurntSushi/memchr",
+            "homepage": "https://github.com/BurntSushi/memchr",
+            "documentation": "https://docs.rs/memchr/",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "memmap",
+            "version": "0.6.2",
+            "id": "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT/Apache-2.0",
+            "license_file": null,
+            "description": "Cross-platform Rust API for memory-mapped file IO",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "tempdir",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "libc",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": "cfg(unix)",
+                    "registry": null
+                },
+                {
+                    "name": "winapi",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [
+                        "basetsd",
+                        "handleapi",
+                        "memoryapi",
+                        "minwindef",
+                        "std",
+                        "sysinfoapi"
+                    ],
+                    "target": "cfg(windows)",
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "memmap",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/memmap-0.6.2/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "cat",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/memmap-0.6.2/examples/cat.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/memmap-0.6.2/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Dan Burkert <dan@danburkert.com>"
+            ],
+            "categories": [],
+            "keywords": [
+                "mmap",
+                "memory-map",
+                "io",
+                "file"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/danburkert/memmap-rs",
+            "homepage": null,
+            "documentation": "https://docs.rs/memmap",
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "pkg-config",
+            "version": "0.3.26",
+            "id": "pkg-config 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "A library to run the pkg-config system tool at build time in order to be used in\nCargo build scripts.\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "lazy_static",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "pkg-config",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/pkg-config-0.3.26/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/pkg-config-0.3.26/tests/test.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/pkg-config-0.3.26/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Alex Crichton <alex@alexcrichton.com>"
+            ],
+            "categories": [],
+            "keywords": [
+                "build-dependencies"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/rust-lang/pkg-config-rs",
+            "homepage": null,
+            "documentation": "https://docs.rs/pkg-config",
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "proc-macro2",
+            "version": "1.0.56",
+            "id": "proc-macro2 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "A substitute implementation of the compiler's `proc_macro` API to decouple token-based libraries from the procedural macro use case.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "unicode-ident",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "quote",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rustversion",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "proc-macro2",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/proc-macro2-1.0.56/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "comments",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/proc-macro2-1.0.56/tests/comments.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "features",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/proc-macro2-1.0.56/tests/features.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "marker",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/proc-macro2-1.0.56/tests/marker.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/proc-macro2-1.0.56/tests/test.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_fmt",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/proc-macro2-1.0.56/tests/test_fmt.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_size",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/proc-macro2-1.0.56/tests/test_size.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "custom-build"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "build-script-build",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/proc-macro2-1.0.56/build.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "default": [
+                    "proc-macro"
+                ],
+                "nightly": [],
+                "proc-macro": [],
+                "span-locations": []
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/proc-macro2-1.0.56/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "rustc-args": [
+                            "--cfg",
+                            "procmacro2_semver_exempt"
+                        ],
+                        "rustdoc-args": [
+                            "--cfg",
+                            "procmacro2_semver_exempt",
+                            "--cfg",
+                            "doc_cfg"
+                        ],
+                        "targets": [
+                            "x86_64-unknown-linux-gnu"
+                        ]
+                    }
+                },
+                "playground": {
+                    "features": [
+                        "span-locations"
+                    ]
+                }
+            },
+            "publish": null,
+            "authors": [
+                "David Tolnay <dtolnay@gmail.com>",
+                "Alex Crichton <alex@alexcrichton.com>"
+            ],
+            "categories": [
+                "development-tools::procedural-macro-helpers"
+            ],
+            "keywords": [
+                "macros",
+                "syn"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/dtolnay/proc-macro2",
+            "homepage": null,
+            "documentation": "https://docs.rs/proc-macro2",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.31"
+        },
+        {
+            "name": "quickcheck",
+            "version": "1.0.3",
+            "id": "quickcheck 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "Unlicense/MIT",
+            "license_file": null,
+            "description": "Automatic property based testing with shrinking.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "env_logger",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.8.2",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "log",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.4",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rand",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.8",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [
+                        "getrandom",
+                        "small_rng"
+                    ],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "quickcheck",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/quickcheck-1.0.3/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "btree_set_range",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/quickcheck-1.0.3/examples/btree_set_range.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "out_of_bounds",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/quickcheck-1.0.3/examples/out_of_bounds.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "reverse",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/quickcheck-1.0.3/examples/reverse.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "reverse_single",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/quickcheck-1.0.3/examples/reverse_single.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "sieve",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/quickcheck-1.0.3/examples/sieve.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "sort",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/quickcheck-1.0.3/examples/sort.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "default": [
+                    "regex",
+                    "use_logging"
+                ],
+                "env_logger": [
+                    "dep:env_logger"
+                ],
+                "log": [
+                    "dep:log"
+                ],
+                "regex": [
+                    "env_logger/regex"
+                ],
+                "use_logging": [
+                    "log",
+                    "env_logger"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/quickcheck-1.0.3/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>"
+            ],
+            "categories": [
+                "development-tools::testing"
+            ],
+            "keywords": [
+                "testing",
+                "quickcheck",
+                "property",
+                "shrinking",
+                "fuzz"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/BurntSushi/quickcheck",
+            "homepage": "https://github.com/BurntSushi/quickcheck",
+            "documentation": "https://docs.rs/quickcheck",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "quote",
+            "version": "1.0.26",
+            "id": "quote 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "Quasi-quoting macro quote!(...)",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "proc-macro2",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.52",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rustversion",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "trybuild",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.66",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [
+                        "diff"
+                    ],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "quote",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/quote-1.0.26/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "compiletest",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/quote-1.0.26/tests/compiletest.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/quote-1.0.26/tests/test.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "custom-build"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "build-script-build",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/quote-1.0.26/build.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "default": [
+                    "proc-macro"
+                ],
+                "proc-macro": [
+                    "proc-macro2/proc-macro"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/quote-1.0.26/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "targets": [
+                            "x86_64-unknown-linux-gnu"
+                        ]
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "David Tolnay <dtolnay@gmail.com>"
+            ],
+            "categories": [
+                "development-tools::procedural-macro-helpers"
+            ],
+            "keywords": [
+                "macros",
+                "syn"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/dtolnay/quote",
+            "homepage": null,
+            "documentation": "https://docs.rs/quote/",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.31"
+        },
+        {
+            "name": "rand",
+            "version": "0.8.5",
+            "id": "rand 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "Random number generators and other randomness functionality.\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "log",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.4.4",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "packed_simd_2",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3.7",
+                    "kind": null,
+                    "rename": "packed_simd",
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [
+                        "into_bits"
+                    ],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rand_chacha",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rand_core",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.6.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.103",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [
+                        "derive"
+                    ],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "bincode",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.2.1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rand_pcg",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "libc",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2.22",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": "cfg(unix)",
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "rand",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/rand-0.8.5/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                }
+            ],
+            "features": {
+                "alloc": [
+                    "rand_core/alloc"
+                ],
+                "default": [
+                    "std",
+                    "std_rng"
+                ],
+                "getrandom": [
+                    "rand_core/getrandom"
+                ],
+                "libc": [
+                    "dep:libc"
+                ],
+                "log": [
+                    "dep:log"
+                ],
+                "min_const_gen": [],
+                "nightly": [],
+                "packed_simd": [
+                    "dep:packed_simd"
+                ],
+                "rand_chacha": [
+                    "dep:rand_chacha"
+                ],
+                "serde": [
+                    "dep:serde"
+                ],
+                "serde1": [
+                    "serde",
+                    "rand_core/serde1"
+                ],
+                "simd_support": [
+                    "packed_simd"
+                ],
+                "small_rng": [],
+                "std": [
+                    "rand_core/std",
+                    "rand_chacha/std",
+                    "alloc",
+                    "getrandom",
+                    "libc"
+                ],
+                "std_rng": [
+                    "rand_chacha"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/rand-0.8.5/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "all-features": true,
+                        "rustdoc-args": [
+                            "--cfg",
+                            "doc_cfg"
+                        ]
+                    }
+                },
+                "playground": {
+                    "features": [
+                        "small_rng",
+                        "serde1"
+                    ]
+                }
+            },
+            "publish": null,
+            "authors": [
+                "The Rand Project Developers",
+                "The Rust Project Developers"
+            ],
+            "categories": [
+                "algorithms",
+                "no-std"
+            ],
+            "keywords": [
+                "random",
+                "rng"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/rust-random/rand",
+            "homepage": "https://rust-random.github.io/book",
+            "documentation": "https://docs.rs/rand",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "rand_core",
+            "version": "0.6.4",
+            "id": "rand_core 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "Core random number generator traits and tools for implementation.\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "getrandom",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [
+                        "derive"
+                    ],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "rand_core",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/rand_core-0.6.4/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                }
+            ],
+            "features": {
+                "alloc": [],
+                "getrandom": [
+                    "dep:getrandom"
+                ],
+                "serde": [
+                    "dep:serde"
+                ],
+                "serde1": [
+                    "serde"
+                ],
+                "std": [
+                    "alloc",
+                    "getrandom",
+                    "getrandom/std"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/rand_core-0.6.4/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "all-features": true,
+                        "rustdoc-args": [
+                            "--cfg",
+                            "doc_cfg"
+                        ]
+                    }
+                },
+                "playground": {
+                    "all-features": true
+                }
+            },
+            "publish": null,
+            "authors": [
+                "The Rand Project Developers",
+                "The Rust Project Developers"
+            ],
+            "categories": [
+                "algorithms",
+                "no-std"
+            ],
+            "keywords": [
+                "random",
+                "rng"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/rust-random/rand",
+            "homepage": "https://rust-random.github.io/book",
+            "documentation": "https://docs.rs/rand_core",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "regex",
+            "version": "1.7.1",
+            "id": "regex 1.7.1 (path+file:///$ROOT$regex)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "An implementation of regular expressions for Rust. This implementation uses\nfinite automata and guarantees linear time matching on all inputs.\n",
+            "source": null,
+            "dependencies": [
+                {
+                    "name": "aho-corasick",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.7.18",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "memchr",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^2.4.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "regex-syntax",
+                    "source": null,
+                    "req": "^0.6.27",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null,
+                    "path": "$ROOT$regex/regex-syntax"
+                },
+                {
+                    "name": "lazy_static",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "quickcheck",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.3",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rand",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.8.3",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [
+                        "getrandom",
+                        "small_rng"
+                    ],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "regex",
+                    "src_path": "$ROOT$regex/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "shootout-regex-dna-bytes",
+                    "src_path": "$ROOT$regex/examples/shootout-regex-dna-bytes.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "shootout-regex-dna-cheat",
+                    "src_path": "$ROOT$regex/examples/shootout-regex-dna-cheat.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "shootout-regex-dna-replace",
+                    "src_path": "$ROOT$regex/examples/shootout-regex-dna-replace.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "shootout-regex-dna-single-cheat",
+                    "src_path": "$ROOT$regex/examples/shootout-regex-dna-single-cheat.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "shootout-regex-dna-single",
+                    "src_path": "$ROOT$regex/examples/shootout-regex-dna-single.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "shootout-regex-dna",
+                    "src_path": "$ROOT$regex/examples/shootout-regex-dna.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "default",
+                    "src_path": "$ROOT$regex/tests/test_default.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "default-bytes",
+                    "src_path": "$ROOT$regex/tests/test_default_bytes.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "nfa",
+                    "src_path": "$ROOT$regex/tests/test_nfa.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "nfa-utf8bytes",
+                    "src_path": "$ROOT$regex/tests/test_nfa_utf8bytes.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "nfa-bytes",
+                    "src_path": "$ROOT$regex/tests/test_nfa_bytes.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "backtrack",
+                    "src_path": "$ROOT$regex/tests/test_backtrack.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "backtrack-utf8bytes",
+                    "src_path": "$ROOT$regex/tests/test_backtrack_utf8bytes.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "backtrack-bytes",
+                    "src_path": "$ROOT$regex/tests/test_backtrack_bytes.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "crates-regex",
+                    "src_path": "$ROOT$regex/tests/test_crates_regex.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                }
+            ],
+            "features": {
+                "aho-corasick": [
+                    "dep:aho-corasick"
+                ],
+                "default": [
+                    "std",
+                    "perf",
+                    "unicode",
+                    "regex-syntax/default"
+                ],
+                "memchr": [
+                    "dep:memchr"
+                ],
+                "pattern": [],
+                "perf": [
+                    "perf-cache",
+                    "perf-dfa",
+                    "perf-inline",
+                    "perf-literal"
+                ],
+                "perf-cache": [],
+                "perf-dfa": [],
+                "perf-inline": [],
+                "perf-literal": [
+                    "aho-corasick",
+                    "memchr"
+                ],
+                "std": [],
+                "unicode": [
+                    "unicode-age",
+                    "unicode-bool",
+                    "unicode-case",
+                    "unicode-gencat",
+                    "unicode-perl",
+                    "unicode-script",
+                    "unicode-segment",
+                    "regex-syntax/unicode"
+                ],
+                "unicode-age": [
+                    "regex-syntax/unicode-age"
+                ],
+                "unicode-bool": [
+                    "regex-syntax/unicode-bool"
+                ],
+                "unicode-case": [
+                    "regex-syntax/unicode-case"
+                ],
+                "unicode-gencat": [
+                    "regex-syntax/unicode-gencat"
+                ],
+                "unicode-perl": [
+                    "regex-syntax/unicode-perl"
+                ],
+                "unicode-script": [
+                    "regex-syntax/unicode-script"
+                ],
+                "unicode-segment": [
+                    "regex-syntax/unicode-segment"
+                ],
+                "unstable": [
+                    "pattern"
+                ],
+                "use_std": [
+                    "std"
+                ]
+            },
+            "manifest_path": "$ROOT$regex/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "The Rust Project Developers"
+            ],
+            "categories": [
+                "text-processing"
+            ],
+            "keywords": [],
+            "readme": "README.md",
+            "repository": "https://github.com/rust-lang/regex",
+            "homepage": "https://github.com/rust-lang/regex",
+            "documentation": "https://docs.rs/regex",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "regex",
+            "version": "1.8.1",
+            "id": "regex 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "An implementation of regular expressions for Rust. This implementation uses\nfinite automata and guarantees linear time matching on all inputs.\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "aho-corasick",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "memchr",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^2.5.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "regex-syntax",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.7.1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "lazy_static",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "quickcheck",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.3",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rand",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.8.3",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [
+                        "getrandom",
+                        "small_rng"
+                    ],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "regex",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/src/lib.rs",
+                    "edition": "2021",
+                    "doc": true,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "shootout-regex-dna-bytes",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/examples/shootout-regex-dna-bytes.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "shootout-regex-dna-cheat",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/examples/shootout-regex-dna-cheat.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "shootout-regex-dna-replace",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/examples/shootout-regex-dna-replace.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "shootout-regex-dna-single-cheat",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/examples/shootout-regex-dna-single-cheat.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "shootout-regex-dna-single",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/examples/shootout-regex-dna-single.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "shootout-regex-dna",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/examples/shootout-regex-dna.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "default",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/tests/test_default.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "default-bytes",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/tests/test_default_bytes.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "nfa",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/tests/test_nfa.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "nfa-utf8bytes",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/tests/test_nfa_utf8bytes.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "nfa-bytes",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/tests/test_nfa_bytes.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "backtrack",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/tests/test_backtrack.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "backtrack-utf8bytes",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/tests/test_backtrack_utf8bytes.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "backtrack-bytes",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/tests/test_backtrack_bytes.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "crates-regex",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/tests/test_crates_regex.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                }
+            ],
+            "features": {
+                "aho-corasick": [
+                    "dep:aho-corasick"
+                ],
+                "default": [
+                    "std",
+                    "perf",
+                    "unicode",
+                    "regex-syntax/default"
+                ],
+                "memchr": [
+                    "dep:memchr"
+                ],
+                "pattern": [],
+                "perf": [
+                    "perf-cache",
+                    "perf-dfa",
+                    "perf-inline",
+                    "perf-literal"
+                ],
+                "perf-cache": [],
+                "perf-dfa": [],
+                "perf-inline": [],
+                "perf-literal": [
+                    "aho-corasick",
+                    "memchr"
+                ],
+                "std": [],
+                "unicode": [
+                    "unicode-age",
+                    "unicode-bool",
+                    "unicode-case",
+                    "unicode-gencat",
+                    "unicode-perl",
+                    "unicode-script",
+                    "unicode-segment",
+                    "regex-syntax/unicode"
+                ],
+                "unicode-age": [
+                    "regex-syntax/unicode-age"
+                ],
+                "unicode-bool": [
+                    "regex-syntax/unicode-bool"
+                ],
+                "unicode-case": [
+                    "regex-syntax/unicode-case"
+                ],
+                "unicode-gencat": [
+                    "regex-syntax/unicode-gencat"
+                ],
+                "unicode-perl": [
+                    "regex-syntax/unicode-perl"
+                ],
+                "unicode-script": [
+                    "regex-syntax/unicode-script"
+                ],
+                "unicode-segment": [
+                    "regex-syntax/unicode-segment"
+                ],
+                "unstable": [
+                    "pattern"
+                ],
+                "use_std": [
+                    "std"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "The Rust Project Developers"
+            ],
+            "categories": [
+                "text-processing"
+            ],
+            "keywords": [],
+            "readme": "README.md",
+            "repository": "https://github.com/rust-lang/regex",
+            "homepage": "https://github.com/rust-lang/regex",
+            "documentation": "https://docs.rs/regex",
+            "edition": "2021",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.60.0"
+        },
+        {
+            "name": "regex-benchmark",
+            "version": "0.1.0",
+            "id": "regex-benchmark 0.1.0 (path+file:///$ROOT$regex/bench)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "Regex benchmarks for Rust's and other engines.",
+            "source": null,
+            "dependencies": [
+                {
+                    "name": "cfg-if",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "docopt",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "lazy_static",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "libc",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "libpcre-sys",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "memmap",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.6.2",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "onig",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^3",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "regex",
+                    "source": null,
+                    "req": "^1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null,
+                    "path": "$ROOT$regex"
+                },
+                {
+                    "name": "regex-syntax",
+                    "source": null,
+                    "req": "^0.6",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null,
+                    "path": "$ROOT$regex/regex-syntax"
+                },
+                {
+                    "name": "serde",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [
+                        "derive"
+                    ],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "cc",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "build",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "pkg-config",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3.9",
+                    "kind": "build",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "bin"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "regex-run-one",
+                    "src_path": "$ROOT$regex/bench/src/main.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bench"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "bench",
+                    "src_path": "$ROOT$regex/bench/src/bench.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "custom-build"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "build-script-build",
+                    "src_path": "$ROOT$regex/bench/build.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "libpcre-sys": [
+                    "dep:libpcre-sys"
+                ],
+                "onig": [
+                    "dep:onig"
+                ],
+                "re-onig": [
+                    "onig"
+                ],
+                "re-pcre1": [
+                    "libpcre-sys"
+                ],
+                "re-pcre2": [],
+                "re-re2": [],
+                "re-rust": [],
+                "re-rust-bytes": [],
+                "re-tcl": []
+            },
+            "manifest_path": "$ROOT$regex/bench/Cargo.toml",
+            "metadata": null,
+            "publish": [],
+            "authors": [
+                "The Rust Project Developers"
+            ],
+            "categories": [],
+            "keywords": [],
+            "readme": null,
+            "repository": "https://github.com/rust-lang/regex",
+            "homepage": "https://github.com/rust-lang/regex",
+            "documentation": "https://docs.rs/regex",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "regex-debug",
+            "version": "0.1.0",
+            "id": "regex-debug 0.1.0 (path+file:///$ROOT$regex/regex-debug)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "A tool useful for debugging regular expressions.",
+            "source": null,
+            "dependencies": [
+                {
+                    "name": "docopt",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "regex",
+                    "source": null,
+                    "req": "^1.1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null,
+                    "path": "$ROOT$regex"
+                },
+                {
+                    "name": "regex-syntax",
+                    "source": null,
+                    "req": "^0.6",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null,
+                    "path": "$ROOT$regex/regex-syntax"
+                },
+                {
+                    "name": "serde",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [
+                        "derive"
+                    ],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "bin"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "regex-debug",
+                    "src_path": "$ROOT$regex/regex-debug/src/main.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": false,
+                    "test": true
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$regex/regex-debug/Cargo.toml",
+            "metadata": null,
+            "publish": [],
+            "authors": [
+                "The Rust Project Developers"
+            ],
+            "categories": [],
+            "keywords": [],
+            "readme": null,
+            "repository": "https://github.com/rust-lang/regex",
+            "homepage": "https://github.com/rust-lang/regex",
+            "documentation": "https://docs.rs/regex",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "regex-syntax",
+            "version": "0.6.28",
+            "id": "regex-syntax 0.6.28 (path+file:///$ROOT$regex/regex-syntax)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "A regular expression parser.",
+            "source": null,
+            "dependencies": [],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "regex-syntax",
+                    "src_path": "$ROOT$regex/regex-syntax/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bench"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "bench",
+                    "src_path": "$ROOT$regex/regex-syntax/benches/bench.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "default": [
+                    "unicode"
+                ],
+                "unicode": [
+                    "unicode-age",
+                    "unicode-bool",
+                    "unicode-case",
+                    "unicode-gencat",
+                    "unicode-perl",
+                    "unicode-script",
+                    "unicode-segment"
+                ],
+                "unicode-age": [],
+                "unicode-bool": [],
+                "unicode-case": [],
+                "unicode-gencat": [],
+                "unicode-perl": [],
+                "unicode-script": [],
+                "unicode-segment": []
+            },
+            "manifest_path": "$ROOT$regex/regex-syntax/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "The Rust Project Developers"
+            ],
+            "categories": [],
+            "keywords": [],
+            "readme": "README.md",
+            "repository": "https://github.com/rust-lang/regex",
+            "homepage": "https://github.com/rust-lang/regex",
+            "documentation": "https://docs.rs/regex-syntax",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "regex-syntax",
+            "version": "0.7.1",
+            "id": "regex-syntax 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "A regular expression parser.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "regex-syntax",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-syntax-0.7.1/src/lib.rs",
+                    "edition": "2021",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bench"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "bench",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-syntax-0.7.1/benches/bench.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "default": [
+                    "std",
+                    "unicode"
+                ],
+                "std": [],
+                "unicode": [
+                    "unicode-age",
+                    "unicode-bool",
+                    "unicode-case",
+                    "unicode-gencat",
+                    "unicode-perl",
+                    "unicode-script",
+                    "unicode-segment"
+                ],
+                "unicode-age": [],
+                "unicode-bool": [],
+                "unicode-case": [],
+                "unicode-gencat": [],
+                "unicode-perl": [],
+                "unicode-script": [],
+                "unicode-segment": []
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-syntax-0.7.1/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "all-features": true,
+                        "rustdoc-args": [
+                            "--cfg",
+                            "docsrs"
+                        ]
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "The Rust Project Developers"
+            ],
+            "categories": [],
+            "keywords": [],
+            "readme": "README.md",
+            "repository": "https://github.com/rust-lang/regex",
+            "homepage": "https://github.com/rust-lang/regex",
+            "documentation": "https://docs.rs/regex-syntax",
+            "edition": "2021",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.60.0"
+        },
+        {
+            "name": "rure",
+            "version": "0.2.2",
+            "id": "rure 0.2.2 (path+file:///$ROOT$regex/regex-capi)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "A C API for Rust's regular expression library.\n",
+            "source": null,
+            "dependencies": [
+                {
+                    "name": "libc",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "regex",
+                    "source": null,
+                    "req": "^1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null,
+                    "path": "$ROOT$regex"
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "staticlib",
+                        "cdylib",
+                        "rlib"
+                    ],
+                    "crate_types": [
+                        "staticlib",
+                        "cdylib",
+                        "rlib"
+                    ],
+                    "name": "rure",
+                    "src_path": "$ROOT$regex/regex-capi/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$regex/regex-capi/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "The Rust Project Developers"
+            ],
+            "categories": [],
+            "keywords": [],
+            "readme": "README.md",
+            "repository": "https://github.com/rust-lang/regex",
+            "homepage": "https://github.com/rust-lang/regex",
+            "documentation": "https://github.com/rust-lang/regex/tree/master/regex-capi",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "serde",
+            "version": "1.0.160",
+            "id": "serde 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "A generic serialization/deserialization framework",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "serde_derive",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "=1.0.160",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde_derive",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "serde",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.160/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "custom-build"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "build-script-build",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.160/build.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "alloc": [],
+                "default": [
+                    "std"
+                ],
+                "derive": [
+                    "serde_derive"
+                ],
+                "rc": [],
+                "serde_derive": [
+                    "dep:serde_derive"
+                ],
+                "std": [],
+                "unstable": []
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.160/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "features": [
+                            "derive"
+                        ],
+                        "targets": [
+                            "x86_64-unknown-linux-gnu"
+                        ]
+                    }
+                },
+                "playground": {
+                    "features": [
+                        "derive",
+                        "rc"
+                    ]
+                }
+            },
+            "publish": null,
+            "authors": [
+                "Erick Tryzelaar <erick.tryzelaar@gmail.com>",
+                "David Tolnay <dtolnay@gmail.com>"
+            ],
+            "categories": [
+                "encoding",
+                "no-std"
+            ],
+            "keywords": [
+                "serde",
+                "serialization",
+                "no_std"
+            ],
+            "readme": "crates-io.md",
+            "repository": "https://github.com/serde-rs/serde",
+            "homepage": "https://serde.rs",
+            "documentation": "https://docs.rs/serde",
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.19"
+        },
+        {
+            "name": "serde_derive",
+            "version": "1.0.160",
+            "id": "serde_derive 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "proc-macro2",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "quote",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "syn",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^2.0.3",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "proc-macro"
+                    ],
+                    "crate_types": [
+                        "proc-macro"
+                    ],
+                    "name": "serde_derive",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde_derive-1.0.160/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "custom-build"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "build-script-build",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde_derive-1.0.160/build.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "default": [],
+                "deserialize_in_place": []
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde_derive-1.0.160/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "targets": [
+                            "x86_64-unknown-linux-gnu"
+                        ]
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "Erick Tryzelaar <erick.tryzelaar@gmail.com>",
+                "David Tolnay <dtolnay@gmail.com>"
+            ],
+            "categories": [
+                "no-std"
+            ],
+            "keywords": [
+                "serde",
+                "serialization",
+                "no_std",
+                "derive"
+            ],
+            "readme": "crates-io.md",
+            "repository": "https://github.com/serde-rs/serde",
+            "homepage": "https://serde.rs",
+            "documentation": "https://serde.rs/derive.html",
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.56"
+        },
+        {
+            "name": "strsim",
+            "version": "0.10.0",
+            "id": "strsim 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT",
+            "license_file": null,
+            "description": "Implementations of string similarity metrics. Includes Hamming, Levenshtein,\nOSA, Damerau-Levenshtein, Jaro, Jaro-Winkler, and Sørensen-Dice.\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "strsim",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/strsim-0.10.0/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "lib",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/strsim-0.10.0/tests/lib.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bench"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "benches",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/strsim-0.10.0/benches/benches.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/strsim-0.10.0/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Danny Guo <danny@dannyguo.com>"
+            ],
+            "categories": [],
+            "keywords": [
+                "string",
+                "similarity",
+                "Hamming",
+                "Levenshtein",
+                "Jaro"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/dguo/strsim-rs",
+            "homepage": "https://github.com/dguo/strsim-rs",
+            "documentation": "https://docs.rs/strsim/",
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "syn",
+            "version": "2.0.15",
+            "id": "syn 2.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "Parser for Rust source code",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "proc-macro2",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.55",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "quote",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.25",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "unicode-ident",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "anyhow",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "automod",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "flate2",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "insta",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rayon",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "ref-cast",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "regex",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "reqwest",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.11",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [
+                        "blocking"
+                    ],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rustversion",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "syn-test-suite",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "tar",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.4.16",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "termcolor",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "walkdir",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^2.3.2",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "syn",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/src/lib.rs",
+                    "edition": "2021",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "regression",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/regression.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_asyncness",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_asyncness.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_attribute",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_attribute.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_derive_input",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_derive_input.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_expr",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_expr.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_generics",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_generics.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_grouping",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_grouping.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_ident",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_ident.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_item",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_item.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_iterators",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_iterators.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_lit",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_lit.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_meta",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_meta.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_parse_buffer",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_parse_buffer.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_parse_stream",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_parse_stream.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_pat",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_pat.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_path",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_path.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_precedence",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_precedence.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_receiver",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_receiver.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_round_trip",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_round_trip.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_shebang",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_shebang.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_should_parse",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_should_parse.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_size",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_size.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_stmt",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_stmt.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_token_trees",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_token_trees.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_ty",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_ty.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_visibility",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_visibility.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "zzz_stable",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/zzz_stable.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bench"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "rust",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/benches/rust.rs",
+                    "edition": "2021",
+                    "required-features": [
+                        "full",
+                        "parsing"
+                    ],
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "bench"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "file",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/benches/file.rs",
+                    "edition": "2021",
+                    "required-features": [
+                        "full",
+                        "parsing"
+                    ],
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "clone-impls": [],
+                "default": [
+                    "derive",
+                    "parsing",
+                    "printing",
+                    "clone-impls",
+                    "proc-macro"
+                ],
+                "derive": [],
+                "extra-traits": [],
+                "fold": [],
+                "full": [],
+                "parsing": [],
+                "printing": [
+                    "quote"
+                ],
+                "proc-macro": [
+                    "proc-macro2/proc-macro",
+                    "quote/proc-macro"
+                ],
+                "quote": [
+                    "dep:quote"
+                ],
+                "test": [
+                    "syn-test-suite/all-features"
+                ],
+                "visit": [],
+                "visit-mut": []
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "all-features": true,
+                        "rustdoc-args": [
+                            "--cfg",
+                            "doc_cfg"
+                        ],
+                        "targets": [
+                            "x86_64-unknown-linux-gnu"
+                        ]
+                    }
+                },
+                "playground": {
+                    "features": [
+                        "full",
+                        "visit",
+                        "visit-mut",
+                        "fold",
+                        "extra-traits"
+                    ]
+                }
+            },
+            "publish": null,
+            "authors": [
+                "David Tolnay <dtolnay@gmail.com>"
+            ],
+            "categories": [
+                "development-tools::procedural-macro-helpers",
+                "parser-implementations"
+            ],
+            "keywords": [
+                "macros",
+                "syn"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/dtolnay/syn",
+            "homepage": null,
+            "documentation": "https://docs.rs/syn",
+            "edition": "2021",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.56"
+        },
+        {
+            "name": "unicode-ident",
+            "version": "1.0.8",
+            "id": "unicode-ident 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "(MIT OR Apache-2.0) AND Unicode-DFS-2016",
+            "license_file": null,
+            "description": "Determine whether characters have the XID_Start or XID_Continue properties according to Unicode Standard Annex #31",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "criterion",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.4",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "fst",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.4",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rand",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.8",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [
+                        "small_rng"
+                    ],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "roaring",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.10",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "ucd-trie",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "unicode-xid",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2.4",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "unicode-ident",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/unicode-ident-1.0.8/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "compare",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/unicode-ident-1.0.8/tests/compare.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "static_size",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/unicode-ident-1.0.8/tests/static_size.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bench"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "xid",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/unicode-ident-1.0.8/benches/xid.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/unicode-ident-1.0.8/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "targets": [
+                            "x86_64-unknown-linux-gnu"
+                        ]
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "David Tolnay <dtolnay@gmail.com>"
+            ],
+            "categories": [
+                "development-tools::procedural-macro-helpers",
+                "no-std"
+            ],
+            "keywords": [
+                "unicode",
+                "xid"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/dtolnay/unicode-ident",
+            "homepage": null,
+            "documentation": "https://docs.rs/unicode-ident",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.31"
+        },
+        {
+            "name": "wasi",
+            "version": "0.11.0+wasi-snapshot-preview1",
+            "id": "wasi 0.11.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT",
+            "license_file": null,
+            "description": "Experimental WASI API bindings for Rust",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "compiler_builtins",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rustc-std-workspace-core",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": null,
+                    "rename": "core",
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rustc-std-workspace-alloc",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "wasi",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/wasi-0.11.0+wasi-snapshot-preview1/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                }
+            ],
+            "features": {
+                "compiler_builtins": [
+                    "dep:compiler_builtins"
+                ],
+                "core": [
+                    "dep:core"
+                ],
+                "default": [
+                    "std"
+                ],
+                "rustc-dep-of-std": [
+                    "compiler_builtins",
+                    "core",
+                    "rustc-std-workspace-alloc"
+                ],
+                "rustc-std-workspace-alloc": [
+                    "dep:rustc-std-workspace-alloc"
+                ],
+                "std": []
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/wasi-0.11.0+wasi-snapshot-preview1/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "The Cranelift Project Developers"
+            ],
+            "categories": [
+                "no-std",
+                "wasm"
+            ],
+            "keywords": [
+                "webassembly",
+                "wasm"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/bytecodealliance/wasi",
+            "homepage": null,
+            "documentation": "https://docs.rs/wasi",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "winapi",
+            "version": "0.3.9",
+            "id": "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT/Apache-2.0",
+            "license_file": null,
+            "description": "Raw FFI bindings for all of Windows API.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "winapi-i686-pc-windows-gnu",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.4",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": "i686-pc-windows-gnu",
+                    "registry": null
+                },
+                {
+                    "name": "winapi-x86_64-pc-windows-gnu",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.4",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": "x86_64-pc-windows-gnu",
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "winapi",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/winapi-0.3.9/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "custom-build"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "build-script-build",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/winapi-0.3.9/build.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "accctrl": [],
+                "aclapi": [],
+                "activation": [],
+                "adhoc": [],
+                "appmgmt": [],
+                "audioclient": [],
+                "audiosessiontypes": [],
+                "avrt": [],
+                "basetsd": [],
+                "bcrypt": [],
+                "bits": [],
+                "bits10_1": [],
+                "bits1_5": [],
+                "bits2_0": [],
+                "bits2_5": [],
+                "bits3_0": [],
+                "bits4_0": [],
+                "bits5_0": [],
+                "bitscfg": [],
+                "bitsmsg": [],
+                "bluetoothapis": [],
+                "bluetoothleapis": [],
+                "bthdef": [],
+                "bthioctl": [],
+                "bthledef": [],
+                "bthsdpdef": [],
+                "bugcodes": [],
+                "cderr": [],
+                "cfg": [],
+                "cfgmgr32": [],
+                "cguid": [],
+                "combaseapi": [],
+                "coml2api": [],
+                "commapi": [],
+                "commctrl": [],
+                "commdlg": [],
+                "commoncontrols": [],
+                "consoleapi": [],
+                "corecrt": [],
+                "corsym": [],
+                "d2d1": [],
+                "d2d1_1": [],
+                "d2d1_2": [],
+                "d2d1_3": [],
+                "d2d1effectauthor": [],
+                "d2d1effects": [],
+                "d2d1effects_1": [],
+                "d2d1effects_2": [],
+                "d2d1svg": [],
+                "d2dbasetypes": [],
+                "d3d": [],
+                "d3d10": [],
+                "d3d10_1": [],
+                "d3d10_1shader": [],
+                "d3d10effect": [],
+                "d3d10misc": [],
+                "d3d10sdklayers": [],
+                "d3d10shader": [],
+                "d3d11": [],
+                "d3d11_1": [],
+                "d3d11_2": [],
+                "d3d11_3": [],
+                "d3d11_4": [],
+                "d3d11on12": [],
+                "d3d11sdklayers": [],
+                "d3d11shader": [],
+                "d3d11tokenizedprogramformat": [],
+                "d3d12": [],
+                "d3d12sdklayers": [],
+                "d3d12shader": [],
+                "d3d9": [],
+                "d3d9caps": [],
+                "d3d9types": [],
+                "d3dcommon": [],
+                "d3dcompiler": [],
+                "d3dcsx": [],
+                "d3dkmdt": [],
+                "d3dkmthk": [],
+                "d3dukmdt": [],
+                "d3dx10core": [],
+                "d3dx10math": [],
+                "d3dx10mesh": [],
+                "datetimeapi": [],
+                "davclnt": [],
+                "dbghelp": [],
+                "dbt": [],
+                "dcommon": [],
+                "dcomp": [],
+                "dcompanimation": [],
+                "dcomptypes": [],
+                "dde": [],
+                "ddraw": [],
+                "ddrawi": [],
+                "ddrawint": [],
+                "debug": [
+                    "impl-debug"
+                ],
+                "debugapi": [],
+                "devguid": [],
+                "devicetopology": [],
+                "devpkey": [],
+                "devpropdef": [],
+                "dinput": [],
+                "dinputd": [],
+                "dispex": [],
+                "dmksctl": [],
+                "dmusicc": [],
+                "docobj": [],
+                "documenttarget": [],
+                "dot1x": [],
+                "dpa_dsa": [],
+                "dpapi": [],
+                "dsgetdc": [],
+                "dsound": [],
+                "dsrole": [],
+                "dvp": [],
+                "dwmapi": [],
+                "dwrite": [],
+                "dwrite_1": [],
+                "dwrite_2": [],
+                "dwrite_3": [],
+                "dxdiag": [],
+                "dxfile": [],
+                "dxgi": [],
+                "dxgi1_2": [],
+                "dxgi1_3": [],
+                "dxgi1_4": [],
+                "dxgi1_5": [],
+                "dxgi1_6": [],
+                "dxgidebug": [],
+                "dxgiformat": [],
+                "dxgitype": [],
+                "dxva2api": [],
+                "dxvahd": [],
+                "eaptypes": [],
+                "enclaveapi": [],
+                "endpointvolume": [],
+                "errhandlingapi": [],
+                "everything": [],
+                "evntcons": [],
+                "evntprov": [],
+                "evntrace": [],
+                "excpt": [],
+                "exdisp": [],
+                "fibersapi": [],
+                "fileapi": [],
+                "functiondiscoverykeys_devpkey": [],
+                "gl-gl": [],
+                "guiddef": [],
+                "handleapi": [],
+                "heapapi": [],
+                "hidclass": [],
+                "hidpi": [],
+                "hidsdi": [],
+                "hidusage": [],
+                "highlevelmonitorconfigurationapi": [],
+                "hstring": [],
+                "http": [],
+                "ifdef": [],
+                "ifmib": [],
+                "imm": [],
+                "impl-debug": [],
+                "impl-default": [],
+                "in6addr": [],
+                "inaddr": [],
+                "inspectable": [],
+                "interlockedapi": [],
+                "intsafe": [],
+                "ioapiset": [],
+                "ipexport": [],
+                "iphlpapi": [],
+                "ipifcons": [],
+                "ipmib": [],
+                "iprtrmib": [],
+                "iptypes": [],
+                "jobapi": [],
+                "jobapi2": [],
+                "knownfolders": [],
+                "ks": [],
+                "ksmedia": [],
+                "ktmtypes": [],
+                "ktmw32": [],
+                "l2cmn": [],
+                "libloaderapi": [],
+                "limits": [],
+                "lmaccess": [],
+                "lmalert": [],
+                "lmapibuf": [],
+                "lmat": [],
+                "lmcons": [],
+                "lmdfs": [],
+                "lmerrlog": [],
+                "lmjoin": [],
+                "lmmsg": [],
+                "lmremutl": [],
+                "lmrepl": [],
+                "lmserver": [],
+                "lmshare": [],
+                "lmstats": [],
+                "lmsvc": [],
+                "lmuse": [],
+                "lmwksta": [],
+                "lowlevelmonitorconfigurationapi": [],
+                "lsalookup": [],
+                "memoryapi": [],
+                "minschannel": [],
+                "minwinbase": [],
+                "minwindef": [],
+                "mmdeviceapi": [],
+                "mmeapi": [],
+                "mmreg": [],
+                "mmsystem": [],
+                "mprapidef": [],
+                "msaatext": [],
+                "mscat": [],
+                "mschapp": [],
+                "mssip": [],
+                "mstcpip": [],
+                "mswsock": [],
+                "mswsockdef": [],
+                "namedpipeapi": [],
+                "namespaceapi": [],
+                "nb30": [],
+                "ncrypt": [],
+                "netioapi": [],
+                "nldef": [],
+                "ntddndis": [],
+                "ntddscsi": [],
+                "ntddser": [],
+                "ntdef": [],
+                "ntlsa": [],
+                "ntsecapi": [],
+                "ntstatus": [],
+                "oaidl": [],
+                "objbase": [],
+                "objidl": [],
+                "objidlbase": [],
+                "ocidl": [],
+                "ole2": [],
+                "oleauto": [],
+                "olectl": [],
+                "oleidl": [],
+                "opmapi": [],
+                "pdh": [],
+                "perflib": [],
+                "physicalmonitorenumerationapi": [],
+                "playsoundapi": [],
+                "portabledevice": [],
+                "portabledeviceapi": [],
+                "portabledevicetypes": [],
+                "powerbase": [],
+                "powersetting": [],
+                "powrprof": [],
+                "processenv": [],
+                "processsnapshot": [],
+                "processthreadsapi": [],
+                "processtopologyapi": [],
+                "profileapi": [],
+                "propidl": [],
+                "propkey": [],
+                "propkeydef": [],
+                "propsys": [],
+                "prsht": [],
+                "psapi": [],
+                "qos": [],
+                "realtimeapiset": [],
+                "reason": [],
+                "restartmanager": [],
+                "restrictederrorinfo": [],
+                "rmxfguid": [],
+                "roapi": [],
+                "robuffer": [],
+                "roerrorapi": [],
+                "rpc": [],
+                "rpcdce": [],
+                "rpcndr": [],
+                "rtinfo": [],
+                "sapi": [],
+                "sapi51": [],
+                "sapi53": [],
+                "sapiddk": [],
+                "sapiddk51": [],
+                "schannel": [],
+                "sddl": [],
+                "securityappcontainer": [],
+                "securitybaseapi": [],
+                "servprov": [],
+                "setupapi": [],
+                "shellapi": [],
+                "shellscalingapi": [],
+                "shlobj": [],
+                "shobjidl": [],
+                "shobjidl_core": [],
+                "shtypes": [],
+                "softpub": [],
+                "spapidef": [],
+                "spellcheck": [],
+                "sporder": [],
+                "sql": [],
+                "sqlext": [],
+                "sqltypes": [],
+                "sqlucode": [],
+                "sspi": [],
+                "std": [],
+                "stralign": [],
+                "stringapiset": [],
+                "strmif": [],
+                "subauth": [],
+                "synchapi": [],
+                "sysinfoapi": [],
+                "systemtopologyapi": [],
+                "taskschd": [],
+                "tcpestats": [],
+                "tcpmib": [],
+                "textstor": [],
+                "threadpoolapiset": [],
+                "threadpoollegacyapiset": [],
+                "timeapi": [],
+                "timezoneapi": [],
+                "tlhelp32": [],
+                "transportsettingcommon": [],
+                "tvout": [],
+                "udpmib": [],
+                "unknwnbase": [],
+                "urlhist": [],
+                "urlmon": [],
+                "usb": [],
+                "usbioctl": [],
+                "usbiodef": [],
+                "usbscan": [],
+                "usbspec": [],
+                "userenv": [],
+                "usp10": [],
+                "utilapiset": [],
+                "uxtheme": [],
+                "vadefs": [],
+                "vcruntime": [],
+                "vsbackup": [],
+                "vss": [],
+                "vsserror": [],
+                "vswriter": [],
+                "wbemads": [],
+                "wbemcli": [],
+                "wbemdisp": [],
+                "wbemprov": [],
+                "wbemtran": [],
+                "wct": [],
+                "werapi": [],
+                "winbase": [],
+                "wincodec": [],
+                "wincodecsdk": [],
+                "wincon": [],
+                "wincontypes": [],
+                "wincred": [],
+                "wincrypt": [],
+                "windef": [],
+                "windot11": [],
+                "windowsceip": [],
+                "windowsx": [],
+                "winefs": [],
+                "winerror": [],
+                "winevt": [],
+                "wingdi": [],
+                "winhttp": [],
+                "wininet": [],
+                "winineti": [],
+                "winioctl": [],
+                "winnetwk": [],
+                "winnls": [],
+                "winnt": [],
+                "winreg": [],
+                "winsafer": [],
+                "winscard": [],
+                "winsmcrd": [],
+                "winsock2": [],
+                "winspool": [],
+                "winstring": [],
+                "winsvc": [],
+                "wintrust": [],
+                "winusb": [],
+                "winusbio": [],
+                "winuser": [],
+                "winver": [],
+                "wlanapi": [],
+                "wlanihv": [],
+                "wlanihvtypes": [],
+                "wlantypes": [],
+                "wlclient": [],
+                "wmistr": [],
+                "wnnc": [],
+                "wow64apiset": [],
+                "wpdmtpextensions": [],
+                "ws2bth": [],
+                "ws2def": [],
+                "ws2ipdef": [],
+                "ws2spi": [],
+                "ws2tcpip": [],
+                "wtsapi32": [],
+                "wtypes": [],
+                "wtypesbase": [],
+                "xinput": []
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/winapi-0.3.9/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "default-target": "x86_64-pc-windows-msvc",
+                        "features": [
+                            "everything",
+                            "impl-debug",
+                            "impl-default"
+                        ],
+                        "targets": [
+                            "aarch64-pc-windows-msvc",
+                            "i686-pc-windows-msvc",
+                            "x86_64-pc-windows-msvc"
+                        ]
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "Peter Atashian <retep998@gmail.com>"
+            ],
+            "categories": [
+                "external-ffi-bindings",
+                "no-std",
+                "os::windows-apis"
+            ],
+            "keywords": [
+                "windows",
+                "ffi",
+                "win32",
+                "com",
+                "directx"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/retep998/winapi-rs",
+            "homepage": null,
+            "documentation": "https://docs.rs/winapi/",
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "winapi-i686-pc-windows-gnu",
+            "version": "0.4.0",
+            "id": "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT/Apache-2.0",
+            "license_file": null,
+            "description": "Import libraries for the i686-pc-windows-gnu target. Please don't use this crate directly, depend on winapi instead.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "winapi-i686-pc-windows-gnu",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/winapi-i686-pc-windows-gnu-0.4.0/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "custom-build"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "build-script-build",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/winapi-i686-pc-windows-gnu-0.4.0/build.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/winapi-i686-pc-windows-gnu-0.4.0/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Peter Atashian <retep998@gmail.com>"
+            ],
+            "categories": [],
+            "keywords": [
+                "windows"
+            ],
+            "readme": null,
+            "repository": "https://github.com/retep998/winapi-rs",
+            "homepage": null,
+            "documentation": null,
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "winapi-x86_64-pc-windows-gnu",
+            "version": "0.4.0",
+            "id": "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT/Apache-2.0",
+            "license_file": null,
+            "description": "Import libraries for the x86_64-pc-windows-gnu target. Please don't use this crate directly, depend on winapi instead.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "winapi-x86_64-pc-windows-gnu",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/winapi-x86_64-pc-windows-gnu-0.4.0/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "custom-build"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "build-script-build",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/winapi-x86_64-pc-windows-gnu-0.4.0/build.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/winapi-x86_64-pc-windows-gnu-0.4.0/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Peter Atashian <retep998@gmail.com>"
+            ],
+            "categories": [],
+            "keywords": [
+                "windows"
+            ],
+            "readme": null,
+            "repository": "https://github.com/retep998/winapi-rs",
+            "homepage": null,
+            "documentation": null,
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        }
+    ],
+    "workspace_members": [
+        "regex-benchmark 0.1.0 (path+file:///$ROOT$regex/bench)",
+        "regex 1.7.1 (path+file:///$ROOT$regex)",
+        "regex-syntax 0.6.28 (path+file:///$ROOT$regex/regex-syntax)",
+        "rure 0.2.2 (path+file:///$ROOT$regex/regex-capi)",
+        "regex-debug 0.1.0 (path+file:///$ROOT$regex/regex-debug)"
+    ],
+    "resolve": {
+        "nodes": [
+            {
+                "id": "aho-corasick 0.7.20 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "memchr",
+                        "pkg": "memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "default",
+                    "std"
+                ]
+            },
+            {
+                "id": "cc 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": []
+            },
+            {
+                "id": "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": []
+            },
+            {
+                "id": "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": []
+            },
+            {
+                "id": "docopt 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "regex 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "serde 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "strsim 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "lazy_static",
+                        "pkg": "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "regex",
+                        "pkg": "regex 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "serde",
+                        "pkg": "serde 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "strsim",
+                        "pkg": "strsim 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "getrandom 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "wasi 0.11.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "cfg_if",
+                        "pkg": "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "libc",
+                        "pkg": "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": "cfg(unix)"
+                            }
+                        ]
+                    },
+                    {
+                        "name": "wasi",
+                        "pkg": "wasi 0.11.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": "cfg(target_os = \"wasi\")"
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": []
+            },
+            {
+                "id": "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": [
+                    "default",
+                    "std"
+                ]
+            },
+            {
+                "id": "memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": [
+                    "default",
+                    "std"
+                ]
+            },
+            {
+                "id": "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "libc",
+                        "pkg": "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": "cfg(unix)"
+                            }
+                        ]
+                    },
+                    {
+                        "name": "winapi",
+                        "pkg": "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": "cfg(windows)"
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "pkg-config 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": []
+            },
+            {
+                "id": "proc-macro2 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "unicode-ident 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "unicode_ident",
+                        "pkg": "unicode-ident 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "default",
+                    "proc-macro"
+                ]
+            },
+            {
+                "id": "quickcheck 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "rand 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "rand",
+                        "pkg": "rand 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "quote 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "proc-macro2 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "proc_macro2",
+                        "pkg": "proc-macro2 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "default",
+                    "proc-macro"
+                ]
+            },
+            {
+                "id": "rand 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "rand_core 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "rand_core",
+                        "pkg": "rand_core 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "getrandom",
+                    "small_rng"
+                ]
+            },
+            {
+                "id": "rand_core 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "getrandom 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "getrandom",
+                        "pkg": "getrandom 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "getrandom"
+                ]
+            },
+            {
+                "id": "regex 1.7.1 (path+file:///$ROOT$regex)",
+                "dependencies": [
+                    "aho-corasick 0.7.20 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "quickcheck 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "rand 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "regex-syntax 0.6.28 (path+file:///$ROOT$regex/regex-syntax)"
+                ],
+                "deps": [
+                    {
+                        "name": "aho_corasick",
+                        "pkg": "aho-corasick 0.7.20 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "lazy_static",
+                        "pkg": "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": "dev",
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "memchr",
+                        "pkg": "memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "quickcheck",
+                        "pkg": "quickcheck 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": "dev",
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "rand",
+                        "pkg": "rand 0.8.5 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": "dev",
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "regex_syntax",
+                        "pkg": "regex-syntax 0.6.28 (path+file:///$ROOT$regex/regex-syntax)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "aho-corasick",
+                    "default",
+                    "memchr",
+                    "perf",
+                    "perf-cache",
+                    "perf-dfa",
+                    "perf-inline",
+                    "perf-literal",
+                    "std",
+                    "unicode",
+                    "unicode-age",
+                    "unicode-bool",
+                    "unicode-case",
+                    "unicode-gencat",
+                    "unicode-perl",
+                    "unicode-script",
+                    "unicode-segment"
+                ]
+            },
+            {
+                "id": "regex 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "regex-syntax 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "regex_syntax",
+                        "pkg": "regex-syntax 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "std",
+                    "unicode",
+                    "unicode-age",
+                    "unicode-bool",
+                    "unicode-case",
+                    "unicode-gencat",
+                    "unicode-perl",
+                    "unicode-script",
+                    "unicode-segment"
+                ]
+            },
+            {
+                "id": "regex-benchmark 0.1.0 (path+file:///$ROOT$regex/bench)",
+                "dependencies": [
+                    "cc 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "docopt 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "pkg-config 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "regex 1.7.1 (path+file:///$ROOT$regex)",
+                    "regex-syntax 0.6.28 (path+file:///$ROOT$regex/regex-syntax)",
+                    "serde 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "cc",
+                        "pkg": "cc 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": "build",
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "cfg_if",
+                        "pkg": "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "docopt",
+                        "pkg": "docopt 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "lazy_static",
+                        "pkg": "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "libc",
+                        "pkg": "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "memmap",
+                        "pkg": "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "pkg_config",
+                        "pkg": "pkg-config 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": "build",
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "regex",
+                        "pkg": "regex 1.7.1 (path+file:///$ROOT$regex)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "regex_syntax",
+                        "pkg": "regex-syntax 0.6.28 (path+file:///$ROOT$regex/regex-syntax)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "serde",
+                        "pkg": "serde 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "regex-debug 0.1.0 (path+file:///$ROOT$regex/regex-debug)",
+                "dependencies": [
+                    "docopt 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "regex 1.7.1 (path+file:///$ROOT$regex)",
+                    "regex-syntax 0.6.28 (path+file:///$ROOT$regex/regex-syntax)",
+                    "serde 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "docopt",
+                        "pkg": "docopt 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "regex",
+                        "pkg": "regex 1.7.1 (path+file:///$ROOT$regex)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "regex_syntax",
+                        "pkg": "regex-syntax 0.6.28 (path+file:///$ROOT$regex/regex-syntax)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "serde",
+                        "pkg": "serde 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "regex-syntax 0.6.28 (path+file:///$ROOT$regex/regex-syntax)",
+                "dependencies": [],
+                "deps": [],
+                "features": [
+                    "default",
+                    "unicode",
+                    "unicode-age",
+                    "unicode-bool",
+                    "unicode-case",
+                    "unicode-gencat",
+                    "unicode-perl",
+                    "unicode-script",
+                    "unicode-segment"
+                ]
+            },
+            {
+                "id": "regex-syntax 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": [
+                    "unicode",
+                    "unicode-age",
+                    "unicode-bool",
+                    "unicode-case",
+                    "unicode-gencat",
+                    "unicode-perl",
+                    "unicode-script",
+                    "unicode-segment"
+                ]
+            },
+            {
+                "id": "rure 0.2.2 (path+file:///$ROOT$regex/regex-capi)",
+                "dependencies": [
+                    "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "regex 1.7.1 (path+file:///$ROOT$regex)"
+                ],
+                "deps": [
+                    {
+                        "name": "libc",
+                        "pkg": "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "regex",
+                        "pkg": "regex 1.7.1 (path+file:///$ROOT$regex)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "serde 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "serde_derive 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "serde_derive",
+                        "pkg": "serde_derive 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "default",
+                    "derive",
+                    "serde_derive",
+                    "std"
+                ]
+            },
+            {
+                "id": "serde_derive 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "proc-macro2 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "quote 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "syn 2.0.15 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "proc_macro2",
+                        "pkg": "proc-macro2 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "quote",
+                        "pkg": "quote 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "syn",
+                        "pkg": "syn 2.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "default"
+                ]
+            },
+            {
+                "id": "strsim 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": []
+            },
+            {
+                "id": "syn 2.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "proc-macro2 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "quote 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "unicode-ident 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "proc_macro2",
+                        "pkg": "proc-macro2 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "quote",
+                        "pkg": "quote 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "unicode_ident",
+                        "pkg": "unicode-ident 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "clone-impls",
+                    "default",
+                    "derive",
+                    "parsing",
+                    "printing",
+                    "proc-macro",
+                    "quote"
+                ]
+            },
+            {
+                "id": "unicode-ident 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": []
+            },
+            {
+                "id": "wasi 0.11.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": []
+            },
+            {
+                "id": "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "winapi_i686_pc_windows_gnu",
+                        "pkg": "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": "i686-pc-windows-gnu"
+                            }
+                        ]
+                    },
+                    {
+                        "name": "winapi_x86_64_pc_windows_gnu",
+                        "pkg": "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": "x86_64-pc-windows-gnu"
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "basetsd",
+                    "handleapi",
+                    "memoryapi",
+                    "minwindef",
+                    "std",
+                    "sysinfoapi"
+                ]
+            },
+            {
+                "id": "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": []
+            },
+            {
+                "id": "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": []
+            }
+        ],
+        "root": "regex 1.7.1 (path+file:///$ROOT$regex)"
+    },
+    "target_directory": "$ROOT$regex/target",
+    "version": 1,
+    "workspace_root": "$ROOT$regex",
+    "metadata": null
+}
diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/ripgrep-metadata.json b/src/tools/rust-analyzer/crates/project-model/test_data/ripgrep-metadata.json
new file mode 100644
index 00000000000..131ff5dd715
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/project-model/test_data/ripgrep-metadata.json
@@ -0,0 +1,12816 @@
+{
+    "packages": [
+        {
+            "name": "aho-corasick",
+            "version": "0.7.20",
+            "id": "aho-corasick 0.7.20 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "Unlicense OR MIT",
+            "license_file": null,
+            "description": "Fast multiple substring searching.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "memchr",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^2.4.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "aho_corasick",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/aho-corasick-0.7.20/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                }
+            ],
+            "features": {
+                "default": [
+                    "std"
+                ],
+                "std": [
+                    "memchr/std"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/aho-corasick-0.7.20/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>"
+            ],
+            "categories": [
+                "text-processing"
+            ],
+            "keywords": [
+                "string",
+                "search",
+                "text",
+                "aho",
+                "multi"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/BurntSushi/aho-corasick",
+            "homepage": "https://github.com/BurntSushi/aho-corasick",
+            "documentation": null,
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "aho-corasick",
+            "version": "1.0.1",
+            "id": "aho-corasick 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "Unlicense OR MIT",
+            "license_file": null,
+            "description": "Fast multiple substring searching.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "log",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.4.17",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "memchr",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^2.4.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "doc-comment",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3.3",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "aho_corasick",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/aho-corasick-1.0.1/src/lib.rs",
+                    "edition": "2021",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                }
+            ],
+            "features": {
+                "default": [
+                    "std",
+                    "perf-literal"
+                ],
+                "logging": [
+                    "dep:log"
+                ],
+                "perf-literal": [
+                    "dep:memchr"
+                ],
+                "std": [
+                    "memchr?/std"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/aho-corasick-1.0.1/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "all-features": true,
+                        "rustdoc-args": [
+                            "--cfg",
+                            "docsrs"
+                        ]
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>"
+            ],
+            "categories": [
+                "text-processing"
+            ],
+            "keywords": [
+                "string",
+                "search",
+                "text",
+                "pattern",
+                "multi"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/BurntSushi/aho-corasick",
+            "homepage": "https://github.com/BurntSushi/aho-corasick",
+            "documentation": null,
+            "edition": "2021",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.60.0"
+        },
+        {
+            "name": "atty",
+            "version": "0.2.14",
+            "id": "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT",
+            "license_file": null,
+            "description": "A simple interface for querying atty",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "hermit-abi",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1.6",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": "cfg(target_os = \"hermit\")",
+                    "registry": null
+                },
+                {
+                    "name": "libc",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": "cfg(unix)",
+                    "registry": null
+                },
+                {
+                    "name": "winapi",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [
+                        "consoleapi",
+                        "processenv",
+                        "minwinbase",
+                        "minwindef",
+                        "winbase"
+                    ],
+                    "target": "cfg(windows)",
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "atty",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/atty-0.2.14/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "atty",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/atty-0.2.14/examples/atty.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/atty-0.2.14/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "softprops <d.tangren@gmail.com>"
+            ],
+            "categories": [],
+            "keywords": [
+                "terminal",
+                "tty",
+                "isatty"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/softprops/atty",
+            "homepage": "https://github.com/softprops/atty",
+            "documentation": "http://softprops.github.io/atty",
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "base64",
+            "version": "0.20.0",
+            "id": "base64 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "encodes and decodes base64 as bytes or utf8",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "criterion",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.4.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rand",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.8.5",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [
+                        "small_rng"
+                    ],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rstest",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.12.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rstest_reuse",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "structopt",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3.26",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "base64",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/base64-0.20.0/src/lib.rs",
+                    "edition": "2021",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "base64",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/base64-0.20.0/examples/base64.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "encode",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/base64-0.20.0/tests/encode.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "tests",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/base64-0.20.0/tests/tests.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bench"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "benchmarks",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/base64-0.20.0/benches/benchmarks.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "alloc": [],
+                "default": [
+                    "std"
+                ],
+                "std": []
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/base64-0.20.0/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Alice Maz <alice@alicemaz.com>",
+                "Marshall Pierce <marshall@mpierce.org>"
+            ],
+            "categories": [
+                "encoding"
+            ],
+            "keywords": [
+                "base64",
+                "utf8",
+                "encode",
+                "decode",
+                "no_std"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/marshallpierce/rust-base64",
+            "homepage": null,
+            "documentation": "https://docs.rs/base64",
+            "edition": "2021",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.57.0"
+        },
+        {
+            "name": "bitflags",
+            "version": "1.3.2",
+            "id": "bitflags 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT/Apache-2.0",
+            "license_file": null,
+            "description": "A macro to generate structures which behave like bitflags.\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "compiler_builtins",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1.2",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rustc-std-workspace-core",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.0",
+                    "kind": null,
+                    "rename": "core",
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rustversion",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde_derive",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde_json",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "trybuild",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "walkdir",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^2.3",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "bitflags",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/bitflags-1.3.2/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "basic",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/bitflags-1.3.2/tests/basic.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "compile",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/bitflags-1.3.2/tests/compile.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                }
+            ],
+            "features": {
+                "compiler_builtins": [
+                    "dep:compiler_builtins"
+                ],
+                "core": [
+                    "dep:core"
+                ],
+                "default": [],
+                "example_generated": [],
+                "rustc-dep-of-std": [
+                    "core",
+                    "compiler_builtins"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/bitflags-1.3.2/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "features": [
+                            "example_generated"
+                        ]
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "The Rust Project Developers"
+            ],
+            "categories": [
+                "no-std"
+            ],
+            "keywords": [
+                "bit",
+                "bitmask",
+                "bitflags",
+                "flags"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/bitflags/bitflags",
+            "homepage": "https://github.com/bitflags/bitflags",
+            "documentation": "https://docs.rs/bitflags",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "bstr",
+            "version": "1.4.0",
+            "id": "bstr 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "A string type that is not required to be valid UTF-8.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "memchr",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^2.4.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "once_cell",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.14.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "regex-automata",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1.5",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.85",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "quickcheck",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "ucd-parse",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1.3",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "unicode-segmentation",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.2.1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "bstr",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/bstr-1.4.0/src/lib.rs",
+                    "edition": "2021",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "graphemes",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/bstr-1.4.0/examples/graphemes.rs",
+                    "edition": "2021",
+                    "required-features": [
+                        "std",
+                        "unicode"
+                    ],
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "lines",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/bstr-1.4.0/examples/lines.rs",
+                    "edition": "2021",
+                    "required-features": [
+                        "std"
+                    ],
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "uppercase",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/bstr-1.4.0/examples/uppercase.rs",
+                    "edition": "2021",
+                    "required-features": [
+                        "std",
+                        "unicode"
+                    ],
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "words",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/bstr-1.4.0/examples/words.rs",
+                    "edition": "2021",
+                    "required-features": [
+                        "std",
+                        "unicode"
+                    ],
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "graphemes-std",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/bstr-1.4.0/examples/graphemes-std.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "lines-std",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/bstr-1.4.0/examples/lines-std.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "uppercase-std",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/bstr-1.4.0/examples/uppercase-std.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "words-std",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/bstr-1.4.0/examples/words-std.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "alloc": [
+                    "serde?/alloc"
+                ],
+                "default": [
+                    "std",
+                    "unicode"
+                ],
+                "serde": [
+                    "dep:serde"
+                ],
+                "std": [
+                    "alloc",
+                    "memchr/std",
+                    "serde?/std"
+                ],
+                "unicode": [
+                    "dep:once_cell",
+                    "dep:regex-automata"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/bstr-1.4.0/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "all-features": true,
+                        "rustdoc-args": [
+                            "--cfg",
+                            "docsrs"
+                        ]
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>"
+            ],
+            "categories": [
+                "text-processing",
+                "encoding"
+            ],
+            "keywords": [
+                "string",
+                "str",
+                "byte",
+                "bytes",
+                "text"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/BurntSushi/bstr",
+            "homepage": "https://github.com/BurntSushi/bstr",
+            "documentation": "https://docs.rs/bstr",
+            "edition": "2021",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.60"
+        },
+        {
+            "name": "bytecount",
+            "version": "0.6.3",
+            "id": "bytecount 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "Apache-2.0/MIT",
+            "license_file": null,
+            "description": "count occurrences of a given byte, or the number of UTF-8 code points, in a byte slice, fast",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "packed_simd_2",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3.8",
+                    "kind": null,
+                    "rename": "packed_simd",
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "criterion",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "quickcheck",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rand",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.8",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "bytecount",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/bytecount-0.6.3/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "check",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/bytecount-0.6.3/tests/check.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bench"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "bench",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/bytecount-0.6.3/benches/bench.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "generic-simd": [
+                    "packed_simd"
+                ],
+                "html_report": [],
+                "packed_simd": [
+                    "dep:packed_simd"
+                ],
+                "runtime-dispatch-simd": []
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/bytecount-0.6.3/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Andre Bogus <bogusandre@gmail.de>",
+                "Joshua Landau <joshua@landau.ws>"
+            ],
+            "categories": [
+                "algorithms",
+                "no-std"
+            ],
+            "keywords": [],
+            "readme": "README.md",
+            "repository": "https://github.com/llogiq/bytecount",
+            "homepage": null,
+            "documentation": null,
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "cc",
+            "version": "1.0.79",
+            "id": "cc 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "A build-time dependency for Cargo build scripts to assist in invoking the native\nC compiler to compile native C code into a static archive to be linked into Rust\ncode.\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "jobserver",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1.16",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "tempfile",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^3",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "cc",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/cc-1.0.79/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bin"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "gcc-shim",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/cc-1.0.79/src/bin/gcc-shim.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "cc_env",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/cc-1.0.79/tests/cc_env.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "cflags",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/cc-1.0.79/tests/cflags.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "cxxflags",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/cc-1.0.79/tests/cxxflags.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/cc-1.0.79/tests/test.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                }
+            ],
+            "features": {
+                "jobserver": [
+                    "dep:jobserver"
+                ],
+                "parallel": [
+                    "jobserver"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/cc-1.0.79/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Alex Crichton <alex@alexcrichton.com>"
+            ],
+            "categories": [
+                "development-tools::build-utils"
+            ],
+            "keywords": [
+                "build-dependencies"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/rust-lang/cc-rs",
+            "homepage": "https://github.com/rust-lang/cc-rs",
+            "documentation": "https://docs.rs/cc",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "cfg-if",
+            "version": "1.0.0",
+            "id": "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT/Apache-2.0",
+            "license_file": null,
+            "description": "A macro to ergonomically define an item depending on a large number of #[cfg]\nparameters. Structured like an if-else chain, the first matching branch is the\nitem that gets emitted.\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "compiler_builtins",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1.2",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rustc-std-workspace-core",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.0",
+                    "kind": null,
+                    "rename": "core",
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "cfg-if",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/cfg-if-1.0.0/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "xcrate",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/cfg-if-1.0.0/tests/xcrate.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                }
+            ],
+            "features": {
+                "compiler_builtins": [
+                    "dep:compiler_builtins"
+                ],
+                "core": [
+                    "dep:core"
+                ],
+                "rustc-dep-of-std": [
+                    "core",
+                    "compiler_builtins"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/cfg-if-1.0.0/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Alex Crichton <alex@alexcrichton.com>"
+            ],
+            "categories": [],
+            "keywords": [],
+            "readme": "README.md",
+            "repository": "https://github.com/alexcrichton/cfg-if",
+            "homepage": "https://github.com/alexcrichton/cfg-if",
+            "documentation": "https://docs.rs/cfg-if",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "clap",
+            "version": "2.34.0",
+            "id": "clap 2.34.0 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT",
+            "license_file": null,
+            "description": "A simple to use, efficient, and full-featured Command Line Argument Parser\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "atty",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2.2",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "bitflags",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "clippy",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "~0.0.166",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "strsim",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.8",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "term_size",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "textwrap",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.11.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "unicode-width",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1.4",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "vec_map",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.8",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "yaml-rust",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3.5",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "lazy_static",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.3",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "regex",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "version-sync",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.8",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "ansi_term",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.12",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": "cfg(not(windows))",
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "clap",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/clap-2.34.0/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                }
+            ],
+            "features": {
+                "ansi_term": [
+                    "dep:ansi_term"
+                ],
+                "atty": [
+                    "dep:atty"
+                ],
+                "clippy": [
+                    "dep:clippy"
+                ],
+                "color": [
+                    "ansi_term",
+                    "atty"
+                ],
+                "debug": [],
+                "default": [
+                    "suggestions",
+                    "color",
+                    "vec_map"
+                ],
+                "doc": [
+                    "yaml"
+                ],
+                "nightly": [],
+                "no_cargo": [],
+                "strsim": [
+                    "dep:strsim"
+                ],
+                "suggestions": [
+                    "strsim"
+                ],
+                "term_size": [
+                    "dep:term_size"
+                ],
+                "unstable": [],
+                "vec_map": [
+                    "dep:vec_map"
+                ],
+                "wrap_help": [
+                    "term_size",
+                    "textwrap/term_size"
+                ],
+                "yaml": [
+                    "yaml-rust"
+                ],
+                "yaml-rust": [
+                    "dep:yaml-rust"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/clap-2.34.0/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "features": [
+                            "doc"
+                        ]
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "Kevin K. <kbknapp@gmail.com>"
+            ],
+            "categories": [
+                "command-line-interface"
+            ],
+            "keywords": [
+                "argument",
+                "cli",
+                "arg",
+                "parser",
+                "parse"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/clap-rs/clap",
+            "homepage": "https://clap.rs/",
+            "documentation": "https://docs.rs/clap/",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "crossbeam-channel",
+            "version": "0.5.8",
+            "id": "crossbeam-channel 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "Multi-producer multi-consumer channels for message passing",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "cfg-if",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "crossbeam-utils",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.8",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "num_cpus",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.13.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rand",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.8",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "signal-hook",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "crossbeam-channel",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-channel-0.5.8/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "fibonacci",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-channel-0.5.8/examples/fibonacci.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "matching",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-channel-0.5.8/examples/matching.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "stopwatch",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-channel-0.5.8/examples/stopwatch.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "after",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-channel-0.5.8/tests/after.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "array",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-channel-0.5.8/tests/array.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "golang",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-channel-0.5.8/tests/golang.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "iter",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-channel-0.5.8/tests/iter.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "list",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-channel-0.5.8/tests/list.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "mpsc",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-channel-0.5.8/tests/mpsc.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "never",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-channel-0.5.8/tests/never.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "ready",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-channel-0.5.8/tests/ready.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "same_channel",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-channel-0.5.8/tests/same_channel.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "select",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-channel-0.5.8/tests/select.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "select_macro",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-channel-0.5.8/tests/select_macro.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "thread_locals",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-channel-0.5.8/tests/thread_locals.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "tick",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-channel-0.5.8/tests/tick.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "zero",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-channel-0.5.8/tests/zero.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bench"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "crossbeam",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-channel-0.5.8/benches/crossbeam.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "crossbeam-utils": [
+                    "dep:crossbeam-utils"
+                ],
+                "default": [
+                    "std"
+                ],
+                "std": [
+                    "crossbeam-utils/std"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-channel-0.5.8/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [],
+            "categories": [
+                "algorithms",
+                "concurrency",
+                "data-structures"
+            ],
+            "keywords": [
+                "channel",
+                "mpmc",
+                "select",
+                "golang",
+                "message"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/crossbeam-rs/crossbeam",
+            "homepage": "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-channel",
+            "documentation": null,
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.38"
+        },
+        {
+            "name": "crossbeam-utils",
+            "version": "0.8.15",
+            "id": "crossbeam-utils 0.8.15 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "Utilities for concurrent programming",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "cfg-if",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rand",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.8",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rustversion",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "loom",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.5",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": "cfg(crossbeam_loom)",
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "crossbeam-utils",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-utils-0.8.15/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "atomic_cell",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-utils-0.8.15/tests/atomic_cell.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "cache_padded",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-utils-0.8.15/tests/cache_padded.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "parker",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-utils-0.8.15/tests/parker.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "sharded_lock",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-utils-0.8.15/tests/sharded_lock.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "thread",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-utils-0.8.15/tests/thread.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "wait_group",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-utils-0.8.15/tests/wait_group.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bench"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "atomic_cell",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-utils-0.8.15/benches/atomic_cell.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "custom-build"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "build-script-build",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-utils-0.8.15/build.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "default": [
+                    "std"
+                ],
+                "loom": [
+                    "dep:loom"
+                ],
+                "nightly": [],
+                "std": []
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/crossbeam-utils-0.8.15/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [],
+            "categories": [
+                "algorithms",
+                "concurrency",
+                "data-structures",
+                "no-std"
+            ],
+            "keywords": [
+                "scoped",
+                "thread",
+                "atomic",
+                "cache"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/crossbeam-rs/crossbeam",
+            "homepage": "https://github.com/crossbeam-rs/crossbeam/tree/master/crossbeam-utils",
+            "documentation": null,
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.38"
+        },
+        {
+            "name": "encoding_rs",
+            "version": "0.8.32",
+            "id": "encoding_rs 0.8.32 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "(Apache-2.0 OR MIT) AND BSD-3-Clause",
+            "license_file": null,
+            "description": "A Gecko-oriented implementation of the Encoding Standard",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "cfg-if",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "packed_simd_2",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3.4",
+                    "kind": null,
+                    "rename": "packed_simd",
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "bincode",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde_derive",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde_json",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "encoding_rs",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/encoding_rs-0.8.32/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                }
+            ],
+            "features": {
+                "alloc": [],
+                "default": [
+                    "alloc"
+                ],
+                "fast-big5-hanzi-encode": [],
+                "fast-gb-hanzi-encode": [],
+                "fast-hangul-encode": [],
+                "fast-hanja-encode": [],
+                "fast-kanji-encode": [],
+                "fast-legacy-encode": [
+                    "fast-hangul-encode",
+                    "fast-hanja-encode",
+                    "fast-kanji-encode",
+                    "fast-gb-hanzi-encode",
+                    "fast-big5-hanzi-encode"
+                ],
+                "less-slow-big5-hanzi-encode": [],
+                "less-slow-gb-hanzi-encode": [],
+                "less-slow-kanji-encode": [],
+                "packed_simd": [
+                    "dep:packed_simd"
+                ],
+                "serde": [
+                    "dep:serde"
+                ],
+                "simd-accel": [
+                    "packed_simd",
+                    "packed_simd/into_bits"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/encoding_rs-0.8.32/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Henri Sivonen <hsivonen@hsivonen.fi>"
+            ],
+            "categories": [
+                "text-processing",
+                "encoding",
+                "web-programming",
+                "internationalization"
+            ],
+            "keywords": [
+                "encoding",
+                "web",
+                "unicode",
+                "charset"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/hsivonen/encoding_rs",
+            "homepage": "https://docs.rs/encoding_rs/",
+            "documentation": "https://docs.rs/encoding_rs/",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "encoding_rs_io",
+            "version": "0.1.7",
+            "id": "encoding_rs_io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "Streaming transcoding for encoding_rs",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "encoding_rs",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.8",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "encoding_rs_io",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/encoding_rs_io-0.1.7/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/encoding_rs_io-0.1.7/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>"
+            ],
+            "categories": [
+                "text-processing",
+                "encoding",
+                "web-programming",
+                "email"
+            ],
+            "keywords": [
+                "encoding",
+                "transcoding",
+                "stream",
+                "io",
+                "read"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/BurntSushi/encoding_rs_io",
+            "homepage": null,
+            "documentation": "https://docs.rs/encoding_rs_io",
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "fnv",
+            "version": "1.0.7",
+            "id": "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "Apache-2.0 / MIT",
+            "license_file": null,
+            "description": "Fowler–Noll–Vo hash function",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "fnv",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/fnv-1.0.7/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                }
+            ],
+            "features": {
+                "default": [
+                    "std"
+                ],
+                "std": []
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/fnv-1.0.7/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Alex Crichton <alex@alexcrichton.com>"
+            ],
+            "categories": [],
+            "keywords": [],
+            "readme": "README.md",
+            "repository": "https://github.com/servo/rust-fnv",
+            "homepage": null,
+            "documentation": "https://doc.servo.org/fnv/",
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "glob",
+            "version": "0.3.1",
+            "id": "glob 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "Support for matching file paths against Unix shell style patterns.\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "doc-comment",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "tempdir",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "glob",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/glob-0.3.1/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "glob-std",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/glob-0.3.1/tests/glob-std.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/glob-0.3.1/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "The Rust Project Developers"
+            ],
+            "categories": [
+                "filesystem"
+            ],
+            "keywords": [],
+            "readme": "README.md",
+            "repository": "https://github.com/rust-lang/glob",
+            "homepage": "https://github.com/rust-lang/glob",
+            "documentation": "https://docs.rs/glob/0.3.1",
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "globset",
+            "version": "0.4.10",
+            "id": "globset 0.4.10 (path+file:///$ROOT$ripgrep/crates/globset)",
+            "license": "Unlicense OR MIT",
+            "license_file": null,
+            "description": "Cross platform single glob and glob set matching. Glob set matching is the\nprocess of matching one or more glob patterns against a single candidate path\nsimultaneously, and returning all of the globs that matched.\n",
+            "source": null,
+            "dependencies": [
+                {
+                    "name": "aho-corasick",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.7.3",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "bstr",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.1.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [
+                        "std"
+                    ],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "fnv",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.6",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "log",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.4.5",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "regex",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.1.5",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [
+                        "perf",
+                        "std"
+                    ],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.104",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "glob",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "lazy_static",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde_json",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.45",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "globset",
+                    "src_path": "$ROOT$ripgrep/crates/globset/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bench"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "bench",
+                    "src_path": "$ROOT$ripgrep/crates/globset/benches/bench.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "default": [
+                    "log"
+                ],
+                "log": [
+                    "dep:log"
+                ],
+                "serde": [
+                    "dep:serde"
+                ],
+                "serde1": [
+                    "serde"
+                ],
+                "simd-accel": []
+            },
+            "manifest_path": "$ROOT$ripgrep/crates/globset/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>"
+            ],
+            "categories": [],
+            "keywords": [
+                "regex",
+                "glob",
+                "multiple",
+                "set",
+                "pattern"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/BurntSushi/ripgrep/tree/master/crates/globset",
+            "homepage": "https://github.com/BurntSushi/ripgrep/tree/master/crates/globset",
+            "documentation": "https://docs.rs/globset",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "grep",
+            "version": "0.2.11",
+            "id": "grep 0.2.11 (path+file:///$ROOT$ripgrep/crates/grep)",
+            "license": "Unlicense OR MIT",
+            "license_file": null,
+            "description": "Fast line oriented regex searching as a library.\n",
+            "source": null,
+            "dependencies": [
+                {
+                    "name": "grep-cli",
+                    "source": null,
+                    "req": "^0.1.7",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null,
+                    "path": "$ROOT$ripgrep/crates/cli"
+                },
+                {
+                    "name": "grep-matcher",
+                    "source": null,
+                    "req": "^0.1.6",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null,
+                    "path": "$ROOT$ripgrep/crates/matcher"
+                },
+                {
+                    "name": "grep-pcre2",
+                    "source": null,
+                    "req": "^0.1.6",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null,
+                    "path": "$ROOT$ripgrep/crates/pcre2"
+                },
+                {
+                    "name": "grep-printer",
+                    "source": null,
+                    "req": "^0.1.7",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null,
+                    "path": "$ROOT$ripgrep/crates/printer"
+                },
+                {
+                    "name": "grep-regex",
+                    "source": null,
+                    "req": "^0.1.11",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null,
+                    "path": "$ROOT$ripgrep/crates/regex"
+                },
+                {
+                    "name": "grep-searcher",
+                    "source": null,
+                    "req": "^0.1.11",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null,
+                    "path": "$ROOT$ripgrep/crates/searcher"
+                },
+                {
+                    "name": "termcolor",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.4",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "walkdir",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^2.2.7",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "grep",
+                    "src_path": "$ROOT$ripgrep/crates/grep/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "simplegrep",
+                    "src_path": "$ROOT$ripgrep/crates/grep/examples/simplegrep.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "avx-accel": [],
+                "grep-pcre2": [
+                    "dep:grep-pcre2"
+                ],
+                "pcre2": [
+                    "grep-pcre2"
+                ],
+                "simd-accel": [
+                    "grep-searcher/simd-accel"
+                ]
+            },
+            "manifest_path": "$ROOT$ripgrep/crates/grep/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>"
+            ],
+            "categories": [],
+            "keywords": [
+                "regex",
+                "grep",
+                "egrep",
+                "search",
+                "pattern"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/BurntSushi/ripgrep/tree/master/crates/grep",
+            "homepage": "https://github.com/BurntSushi/ripgrep/tree/master/crates/grep",
+            "documentation": "https://docs.rs/grep",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "grep-cli",
+            "version": "0.1.7",
+            "id": "grep-cli 0.1.7 (path+file:///$ROOT$ripgrep/crates/cli)",
+            "license": "Unlicense OR MIT",
+            "license_file": null,
+            "description": "Utilities for search oriented command line applications.\n",
+            "source": null,
+            "dependencies": [
+                {
+                    "name": "atty",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2.11",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "bstr",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.1.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "globset",
+                    "source": null,
+                    "req": "^0.4.10",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null,
+                    "path": "$ROOT$ripgrep/crates/globset"
+                },
+                {
+                    "name": "lazy_static",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.1.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "log",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.4.5",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "regex",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "same-file",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.4",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "termcolor",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.4",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "winapi-util",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1.1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": "cfg(windows)",
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "grep-cli",
+                    "src_path": "$ROOT$ripgrep/crates/cli/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$ripgrep/crates/cli/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>"
+            ],
+            "categories": [],
+            "keywords": [
+                "regex",
+                "grep",
+                "cli",
+                "utility",
+                "util"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/BurntSushi/ripgrep/tree/master/crates/cli",
+            "homepage": "https://github.com/BurntSushi/ripgrep/tree/master/crates/cli",
+            "documentation": "https://docs.rs/grep-cli",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "grep-matcher",
+            "version": "0.1.6",
+            "id": "grep-matcher 0.1.6 (path+file:///$ROOT$ripgrep/crates/matcher)",
+            "license": "Unlicense OR MIT",
+            "license_file": null,
+            "description": "A trait for regular expressions, with a focus on line oriented search.\n",
+            "source": null,
+            "dependencies": [
+                {
+                    "name": "memchr",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^2.1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "regex",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "grep-matcher",
+                    "src_path": "$ROOT$ripgrep/crates/matcher/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "integration",
+                    "src_path": "$ROOT$ripgrep/crates/matcher/tests/tests.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$ripgrep/crates/matcher/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>"
+            ],
+            "categories": [],
+            "keywords": [
+                "regex",
+                "pattern",
+                "trait"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/BurntSushi/ripgrep/tree/master/crates/matcher",
+            "homepage": "https://github.com/BurntSushi/ripgrep/tree/master/crates/matcher",
+            "documentation": "https://docs.rs/grep-matcher",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "grep-pcre2",
+            "version": "0.1.6",
+            "id": "grep-pcre2 0.1.6 (path+file:///$ROOT$ripgrep/crates/pcre2)",
+            "license": "Unlicense OR MIT",
+            "license_file": null,
+            "description": "Use PCRE2 with the 'grep' crate.\n",
+            "source": null,
+            "dependencies": [
+                {
+                    "name": "grep-matcher",
+                    "source": null,
+                    "req": "^0.1.6",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null,
+                    "path": "$ROOT$ripgrep/crates/matcher"
+                },
+                {
+                    "name": "pcre2",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2.3",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "grep-pcre2",
+                    "src_path": "$ROOT$ripgrep/crates/pcre2/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$ripgrep/crates/pcre2/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>"
+            ],
+            "categories": [],
+            "keywords": [
+                "regex",
+                "grep",
+                "pcre",
+                "backreference",
+                "look"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/BurntSushi/ripgrep/tree/master/crates/pcre2",
+            "homepage": "https://github.com/BurntSushi/ripgrep/tree/master/crates/pcre2",
+            "documentation": "https://docs.rs/grep-pcre2",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "grep-printer",
+            "version": "0.1.7",
+            "id": "grep-printer 0.1.7 (path+file:///$ROOT$ripgrep/crates/printer)",
+            "license": "Unlicense OR MIT",
+            "license_file": null,
+            "description": "An implementation of the grep crate's Sink trait that provides standard\nprinting of search results, similar to grep itself.\n",
+            "source": null,
+            "dependencies": [
+                {
+                    "name": "base64",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.20.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "bstr",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.1.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "grep-matcher",
+                    "source": null,
+                    "req": "^0.1.6",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null,
+                    "path": "$ROOT$ripgrep/crates/matcher"
+                },
+                {
+                    "name": "grep-searcher",
+                    "source": null,
+                    "req": "^0.1.11",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null,
+                    "path": "$ROOT$ripgrep/crates/searcher"
+                },
+                {
+                    "name": "serde",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.77",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [
+                        "derive"
+                    ],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde_json",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.27",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "termcolor",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.4",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "grep-regex",
+                    "source": null,
+                    "req": "^0.1.11",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null,
+                    "path": "$ROOT$ripgrep/crates/regex"
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "grep-printer",
+                    "src_path": "$ROOT$ripgrep/crates/printer/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                }
+            ],
+            "features": {
+                "base64": [
+                    "dep:base64"
+                ],
+                "default": [
+                    "serde1"
+                ],
+                "serde": [
+                    "dep:serde"
+                ],
+                "serde1": [
+                    "base64",
+                    "serde",
+                    "serde_json"
+                ],
+                "serde_json": [
+                    "dep:serde_json"
+                ]
+            },
+            "manifest_path": "$ROOT$ripgrep/crates/printer/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>"
+            ],
+            "categories": [],
+            "keywords": [
+                "grep",
+                "pattern",
+                "print",
+                "printer",
+                "sink"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/BurntSushi/ripgrep/tree/master/crates/printer",
+            "homepage": "https://github.com/BurntSushi/ripgrep/tree/master/crates/printer",
+            "documentation": "https://docs.rs/grep-printer",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "grep-regex",
+            "version": "0.1.11",
+            "id": "grep-regex 0.1.11 (path+file:///$ROOT$ripgrep/crates/regex)",
+            "license": "Unlicense OR MIT",
+            "license_file": null,
+            "description": "Use Rust's regex library with the 'grep' crate.\n",
+            "source": null,
+            "dependencies": [
+                {
+                    "name": "aho-corasick",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.7.3",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "bstr",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.1.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "grep-matcher",
+                    "source": null,
+                    "req": "^0.1.6",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null,
+                    "path": "$ROOT$ripgrep/crates/matcher"
+                },
+                {
+                    "name": "log",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.4.5",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "regex",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "regex-syntax",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.6.5",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "thread_local",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.1.2",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "grep-regex",
+                    "src_path": "$ROOT$ripgrep/crates/regex/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$ripgrep/crates/regex/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>"
+            ],
+            "categories": [],
+            "keywords": [
+                "regex",
+                "grep",
+                "search",
+                "pattern",
+                "line"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/BurntSushi/ripgrep/tree/master/crates/regex",
+            "homepage": "https://github.com/BurntSushi/ripgrep/tree/master/crates/regex",
+            "documentation": "https://docs.rs/grep-regex",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "grep-searcher",
+            "version": "0.1.11",
+            "id": "grep-searcher 0.1.11 (path+file:///$ROOT$ripgrep/crates/searcher)",
+            "license": "Unlicense OR MIT",
+            "license_file": null,
+            "description": "Fast line oriented regex searching as a library.\n",
+            "source": null,
+            "dependencies": [
+                {
+                    "name": "bstr",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.1.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [
+                        "std"
+                    ],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "bytecount",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.6",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "encoding_rs",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.8.14",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "encoding_rs_io",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1.6",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "grep-matcher",
+                    "source": null,
+                    "req": "^0.1.6",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null,
+                    "path": "$ROOT$ripgrep/crates/matcher"
+                },
+                {
+                    "name": "log",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.4.5",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "memmap2",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.5.3",
+                    "kind": null,
+                    "rename": "memmap",
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "grep-regex",
+                    "source": null,
+                    "req": "^0.1.11",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null,
+                    "path": "$ROOT$ripgrep/crates/regex"
+                },
+                {
+                    "name": "regex",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "grep-searcher",
+                    "src_path": "$ROOT$ripgrep/crates/searcher/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "search-stdin",
+                    "src_path": "$ROOT$ripgrep/crates/searcher/examples/search-stdin.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "avx-accel": [],
+                "default": [
+                    "bytecount/runtime-dispatch-simd"
+                ],
+                "simd-accel": [
+                    "encoding_rs/simd-accel"
+                ]
+            },
+            "manifest_path": "$ROOT$ripgrep/crates/searcher/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>"
+            ],
+            "categories": [],
+            "keywords": [
+                "regex",
+                "grep",
+                "egrep",
+                "search",
+                "pattern"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/BurntSushi/ripgrep/tree/master/crates/searcher",
+            "homepage": "https://github.com/BurntSushi/ripgrep/tree/master/crates/searcher",
+            "documentation": "https://docs.rs/grep-searcher",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "hermit-abi",
+            "version": "0.1.19",
+            "id": "hermit-abi 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT/Apache-2.0",
+            "license_file": null,
+            "description": "hermit-abi is small interface to call functions from the unikernel RustyHermit.\nIt is used to build the target `x86_64-unknown-hermit`.\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "compiler_builtins",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rustc-std-workspace-core",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.0",
+                    "kind": null,
+                    "rename": "core",
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "libc",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2.51",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "hermit-abi",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/hermit-abi-0.1.19/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                }
+            ],
+            "features": {
+                "compiler_builtins": [
+                    "dep:compiler_builtins"
+                ],
+                "core": [
+                    "dep:core"
+                ],
+                "default": [],
+                "docs": [],
+                "rustc-dep-of-std": [
+                    "core",
+                    "compiler_builtins/rustc-dep-of-std",
+                    "libc/rustc-dep-of-std"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/hermit-abi-0.1.19/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "default-target": "x86_64-unknown-hermit",
+                        "features": [
+                            "docs"
+                        ]
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "Stefan Lankes"
+            ],
+            "categories": [
+                "os"
+            ],
+            "keywords": [
+                "unikernel",
+                "libos"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/hermitcore/libhermit-rs",
+            "homepage": null,
+            "documentation": "https://hermitcore.github.io/rusty-hermit/hermit_abi",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "ignore",
+            "version": "0.4.20",
+            "id": "ignore 0.4.20 (path+file:///$ROOT$ripgrep/crates/ignore)",
+            "license": "Unlicense OR MIT",
+            "license_file": null,
+            "description": "A fast library for efficiently matching ignore files such as `.gitignore`\nagainst file paths.\n",
+            "source": null,
+            "dependencies": [
+                {
+                    "name": "globset",
+                    "source": null,
+                    "req": "^0.4.10",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null,
+                    "path": "$ROOT$ripgrep/crates/globset"
+                },
+                {
+                    "name": "lazy_static",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "log",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.4.5",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "memchr",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^2.1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "regex",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "same-file",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.4",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "thread_local",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "walkdir",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^2.2.7",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "crossbeam-channel",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.5.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "winapi-util",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1.2",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": "cfg(windows)",
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "ignore",
+                    "src_path": "$ROOT$ripgrep/crates/ignore/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "walk",
+                    "src_path": "$ROOT$ripgrep/crates/ignore/examples/walk.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "gitignore_matched_path_or_any_parents_tests",
+                    "src_path": "$ROOT$ripgrep/crates/ignore/tests/gitignore_matched_path_or_any_parents_tests.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                }
+            ],
+            "features": {
+                "simd-accel": [
+                    "globset/simd-accel"
+                ]
+            },
+            "manifest_path": "$ROOT$ripgrep/crates/ignore/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>"
+            ],
+            "categories": [],
+            "keywords": [
+                "glob",
+                "ignore",
+                "gitignore",
+                "pattern",
+                "file"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/BurntSushi/ripgrep/tree/master/crates/ignore",
+            "homepage": "https://github.com/BurntSushi/ripgrep/tree/master/crates/ignore",
+            "documentation": "https://docs.rs/ignore",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "itoa",
+            "version": "1.0.6",
+            "id": "itoa 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "Fast integer primitive to string conversion",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "no-panic",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "itoa",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/itoa-1.0.6/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/itoa-1.0.6/tests/test.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bench"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "bench",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/itoa-1.0.6/benches/bench.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "no-panic": [
+                    "dep:no-panic"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/itoa-1.0.6/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "targets": [
+                            "x86_64-unknown-linux-gnu"
+                        ]
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "David Tolnay <dtolnay@gmail.com>"
+            ],
+            "categories": [
+                "value-formatting",
+                "no-std"
+            ],
+            "keywords": [
+                "integer"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/dtolnay/itoa",
+            "homepage": null,
+            "documentation": "https://docs.rs/itoa",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.36"
+        },
+        {
+            "name": "jemalloc-sys",
+            "version": "0.5.3+5.3.0-patched",
+            "id": "jemalloc-sys 0.5.3+5.3.0-patched (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT/Apache-2.0",
+            "license_file": null,
+            "description": "Rust FFI bindings to jemalloc\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "libc",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2.8",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "cc",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.13",
+                    "kind": "build",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "jemalloc-sys",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/jemalloc-sys-0.5.3+5.3.0-patched/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "malloc_conf_empty",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/jemalloc-sys-0.5.3+5.3.0-patched/tests/malloc_conf_empty.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "malloc_conf_set",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/jemalloc-sys-0.5.3+5.3.0-patched/tests/malloc_conf_set.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "unprefixed_malloc",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/jemalloc-sys-0.5.3+5.3.0-patched/tests/unprefixed_malloc.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "custom-build"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "build-script-build",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/jemalloc-sys-0.5.3+5.3.0-patched/build.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "background_threads": [
+                    "background_threads_runtime_support"
+                ],
+                "background_threads_runtime_support": [],
+                "debug": [],
+                "default": [
+                    "background_threads_runtime_support"
+                ],
+                "disable_initial_exec_tls": [],
+                "profiling": [],
+                "stats": [],
+                "unprefixed_malloc_on_supported_platforms": []
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/jemalloc-sys-0.5.3+5.3.0-patched/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "rustdoc-args": [
+                            "--cfg",
+                            "jemallocator_docs"
+                        ]
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "Alex Crichton <alex@alexcrichton.com>",
+                "Gonzalo Brito Gadeschi <gonzalobg88@gmail.com>",
+                "The TiKV Project Developers"
+            ],
+            "categories": [],
+            "keywords": [
+                "allocator",
+                "jemalloc"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/tikv/jemallocator",
+            "homepage": "https://github.com/tikv/jemallocator",
+            "documentation": "https://docs.rs/jemallocator-sys",
+            "edition": "2018",
+            "links": "jemalloc",
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "jemallocator",
+            "version": "0.5.0",
+            "id": "jemallocator 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT/Apache-2.0",
+            "license_file": null,
+            "description": "A Rust allocator backed by jemalloc\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "jemalloc-sys",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.5.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "libc",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2.8",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "paste",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "jemallocator",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/jemallocator-0.5.0/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "background_thread_defaults",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/jemallocator-0.5.0/tests/background_thread_defaults.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "background_thread_enabled",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/jemallocator-0.5.0/tests/background_thread_enabled.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "ffi",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/jemallocator-0.5.0/tests/ffi.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "grow_in_place",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/jemallocator-0.5.0/tests/grow_in_place.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "malloctl",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/jemallocator-0.5.0/tests/malloctl.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "shrink_in_place",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/jemallocator-0.5.0/tests/shrink_in_place.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "smoke",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/jemallocator-0.5.0/tests/smoke.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "smoke_ffi",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/jemallocator-0.5.0/tests/smoke_ffi.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "usable_size",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/jemallocator-0.5.0/tests/usable_size.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bench"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "roundtrip",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/jemallocator-0.5.0/benches/roundtrip.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "alloc_trait": [],
+                "background_threads": [
+                    "jemalloc-sys/background_threads"
+                ],
+                "background_threads_runtime_support": [
+                    "jemalloc-sys/background_threads_runtime_support"
+                ],
+                "debug": [
+                    "jemalloc-sys/debug"
+                ],
+                "default": [
+                    "background_threads_runtime_support"
+                ],
+                "disable_initial_exec_tls": [
+                    "jemalloc-sys/disable_initial_exec_tls"
+                ],
+                "profiling": [
+                    "jemalloc-sys/profiling"
+                ],
+                "stats": [
+                    "jemalloc-sys/stats"
+                ],
+                "unprefixed_malloc_on_supported_platforms": [
+                    "jemalloc-sys/unprefixed_malloc_on_supported_platforms"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/jemallocator-0.5.0/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "features": [],
+                        "rustdoc-args": [
+                            "--cfg",
+                            "jemallocator_docs"
+                        ]
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "Alex Crichton <alex@alexcrichton.com>",
+                "Gonzalo Brito Gadeschi <gonzalobg88@gmail.com>",
+                "Simon Sapin <simon.sapin@exyr.org>",
+                "Steven Fackler <sfackler@gmail.com>",
+                "The TiKV Project Developers"
+            ],
+            "categories": [
+                "memory-management",
+                "api-bindings"
+            ],
+            "keywords": [
+                "allocator",
+                "jemalloc"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/tikv/jemallocator",
+            "homepage": "https://github.com/tikv/jemallocator",
+            "documentation": "https://docs.rs/jemallocator",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "jobserver",
+            "version": "0.1.26",
+            "id": "jobserver 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT/Apache-2.0",
+            "license_file": null,
+            "description": "An implementation of the GNU make jobserver for Rust\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "futures",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "num_cpus",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "tempfile",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^3",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "tokio-core",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "tokio-process",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "libc",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2.50",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": "cfg(unix)",
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "jobserver",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/jobserver-0.1.26/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "client",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/jobserver-0.1.26/tests/client.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "server",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/jobserver-0.1.26/tests/server.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "client-of-myself",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/jobserver-0.1.26/tests/client-of-myself.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "make-as-a-client",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/jobserver-0.1.26/tests/make-as-a-client.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "helper",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/jobserver-0.1.26/tests/helper.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/jobserver-0.1.26/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Alex Crichton <alex@alexcrichton.com>"
+            ],
+            "categories": [],
+            "keywords": [],
+            "readme": "README.md",
+            "repository": "https://github.com/alexcrichton/jobserver-rs",
+            "homepage": "https://github.com/alexcrichton/jobserver-rs",
+            "documentation": "https://docs.rs/jobserver",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "lazy_static",
+            "version": "1.4.0",
+            "id": "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT/Apache-2.0",
+            "license_file": null,
+            "description": "A macro for declaring lazily evaluated statics in Rust.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "spin",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.5.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "doc-comment",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3.1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "lazy_static",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/lazy_static-1.4.0/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "no_std",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/lazy_static-1.4.0/tests/no_std.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/lazy_static-1.4.0/tests/test.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                }
+            ],
+            "features": {
+                "spin": [
+                    "dep:spin"
+                ],
+                "spin_no_std": [
+                    "spin"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/lazy_static-1.4.0/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Marvin Löbel <loebel.marvin@gmail.com>"
+            ],
+            "categories": [
+                "no-std",
+                "rust-patterns",
+                "memory-management"
+            ],
+            "keywords": [
+                "macro",
+                "lazy",
+                "static"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/rust-lang-nursery/lazy-static.rs",
+            "homepage": null,
+            "documentation": "https://docs.rs/lazy_static",
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "libc",
+            "version": "0.2.142",
+            "id": "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "Raw FFI bindings to platform libraries like libc.\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "rustc-std-workspace-core",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "libc",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/libc-0.2.142/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "const_fn",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/libc-0.2.142/tests/const_fn.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "custom-build"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "build-script-build",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/libc-0.2.142/build.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "align": [],
+                "const-extern-fn": [],
+                "default": [
+                    "std"
+                ],
+                "extra_traits": [],
+                "rustc-dep-of-std": [
+                    "align",
+                    "rustc-std-workspace-core"
+                ],
+                "rustc-std-workspace-core": [
+                    "dep:rustc-std-workspace-core"
+                ],
+                "std": [],
+                "use_std": [
+                    "std"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/libc-0.2.142/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "features": [
+                            "const-extern-fn",
+                            "extra_traits"
+                        ]
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "The Rust Project Developers"
+            ],
+            "categories": [
+                "external-ffi-bindings",
+                "no-std",
+                "os"
+            ],
+            "keywords": [
+                "libc",
+                "ffi",
+                "bindings",
+                "operating",
+                "system"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/rust-lang/libc",
+            "homepage": "https://github.com/rust-lang/libc",
+            "documentation": "https://docs.rs/libc/",
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "log",
+            "version": "0.4.17",
+            "id": "log 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "A lightweight logging facade for Rust\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "cfg-if",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "sval",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "=1.0.0-alpha.5",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "value-bag",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "=1.0.0-alpha.9",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rustversion",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [
+                        "derive"
+                    ],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde_test",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "sval",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "=1.0.0-alpha.5",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [
+                        "derive"
+                    ],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "value-bag",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "=1.0.0-alpha.9",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [
+                        "test"
+                    ],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "log",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/log-0.4.17/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "filters",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/log-0.4.17/tests/filters.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "macros",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/log-0.4.17/tests/macros.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bench"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "value",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/log-0.4.17/benches/value.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "custom-build"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "build-script-build",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/log-0.4.17/build.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "kv_unstable": [
+                    "value-bag"
+                ],
+                "kv_unstable_serde": [
+                    "kv_unstable_std",
+                    "value-bag/serde",
+                    "serde"
+                ],
+                "kv_unstable_std": [
+                    "std",
+                    "kv_unstable",
+                    "value-bag/error"
+                ],
+                "kv_unstable_sval": [
+                    "kv_unstable",
+                    "value-bag/sval",
+                    "sval"
+                ],
+                "max_level_debug": [],
+                "max_level_error": [],
+                "max_level_info": [],
+                "max_level_off": [],
+                "max_level_trace": [],
+                "max_level_warn": [],
+                "release_max_level_debug": [],
+                "release_max_level_error": [],
+                "release_max_level_info": [],
+                "release_max_level_off": [],
+                "release_max_level_trace": [],
+                "release_max_level_warn": [],
+                "serde": [
+                    "dep:serde"
+                ],
+                "std": [],
+                "sval": [
+                    "dep:sval"
+                ],
+                "value-bag": [
+                    "dep:value-bag"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/log-0.4.17/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "features": [
+                            "std",
+                            "serde",
+                            "kv_unstable_std",
+                            "kv_unstable_sval",
+                            "kv_unstable_serde"
+                        ]
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "The Rust Project Developers"
+            ],
+            "categories": [
+                "development-tools::debugging"
+            ],
+            "keywords": [
+                "logging"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/rust-lang/log",
+            "homepage": null,
+            "documentation": "https://docs.rs/log",
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "memchr",
+            "version": "2.5.0",
+            "id": "memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "Unlicense/MIT",
+            "license_file": null,
+            "description": "Safe interface to memchr.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "compiler_builtins",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1.2",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rustc-std-workspace-core",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.0",
+                    "kind": null,
+                    "rename": "core",
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "libc",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2.18",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "quickcheck",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.3",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "memchr",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/memchr-2.5.0/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "custom-build"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "build-script-build",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/memchr-2.5.0/build.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "compiler_builtins": [
+                    "dep:compiler_builtins"
+                ],
+                "core": [
+                    "dep:core"
+                ],
+                "default": [
+                    "std"
+                ],
+                "libc": [
+                    "dep:libc"
+                ],
+                "rustc-dep-of-std": [
+                    "core",
+                    "compiler_builtins"
+                ],
+                "std": [],
+                "use_std": [
+                    "std"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/memchr-2.5.0/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>",
+                "bluss"
+            ],
+            "categories": [],
+            "keywords": [
+                "memchr",
+                "char",
+                "scan",
+                "strchr",
+                "string"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/BurntSushi/memchr",
+            "homepage": "https://github.com/BurntSushi/memchr",
+            "documentation": "https://docs.rs/memchr/",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "memmap2",
+            "version": "0.5.10",
+            "id": "memmap2 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "Cross-platform Rust API for memory-mapped file IO",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "stable_deref_trait",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "owning_ref",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.4.1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "tempfile",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^3",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "libc",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": "cfg(unix)",
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "memmap2",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/memmap2-0.5.10/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "cat",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/memmap2-0.5.10/examples/cat.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "stable_deref_trait": [
+                    "dep:stable_deref_trait"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/memmap2-0.5.10/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Dan Burkert <dan@danburkert.com>",
+                "Yevhenii Reizner <razrfalcon@gmail.com>"
+            ],
+            "categories": [],
+            "keywords": [
+                "mmap",
+                "memory-map",
+                "io",
+                "file"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/RazrFalcon/memmap2-rs",
+            "homepage": null,
+            "documentation": "https://docs.rs/memmap2",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "once_cell",
+            "version": "1.17.1",
+            "id": "once_cell 1.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "Single assignment cells and lazy values.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "atomic-polyfill",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": null,
+                    "rename": "atomic_polyfill",
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "critical-section",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": null,
+                    "rename": "critical_section",
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "parking_lot_core",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.9.3",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "critical-section",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.1.1",
+                    "kind": "dev",
+                    "rename": "critical_section",
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [
+                        "std"
+                    ],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "crossbeam-utils",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.8.7",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "lazy_static",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "regex",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.2.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "once_cell",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/once_cell-1.17.1/src/lib.rs",
+                    "edition": "2021",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "bench",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/once_cell-1.17.1/examples/bench.rs",
+                    "edition": "2021",
+                    "required-features": [
+                        "std"
+                    ],
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "bench_acquire",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/once_cell-1.17.1/examples/bench_acquire.rs",
+                    "edition": "2021",
+                    "required-features": [
+                        "std"
+                    ],
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "bench_vs_lazy_static",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/once_cell-1.17.1/examples/bench_vs_lazy_static.rs",
+                    "edition": "2021",
+                    "required-features": [
+                        "std"
+                    ],
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "lazy_static",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/once_cell-1.17.1/examples/lazy_static.rs",
+                    "edition": "2021",
+                    "required-features": [
+                        "std"
+                    ],
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "reentrant_init_deadlocks",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/once_cell-1.17.1/examples/reentrant_init_deadlocks.rs",
+                    "edition": "2021",
+                    "required-features": [
+                        "std"
+                    ],
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "regex",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/once_cell-1.17.1/examples/regex.rs",
+                    "edition": "2021",
+                    "required-features": [
+                        "std"
+                    ],
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_synchronization",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/once_cell-1.17.1/examples/test_synchronization.rs",
+                    "edition": "2021",
+                    "required-features": [
+                        "std"
+                    ],
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "it",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/once_cell-1.17.1/tests/it.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                }
+            ],
+            "features": {
+                "alloc": [
+                    "race"
+                ],
+                "atomic-polyfill": [
+                    "critical-section"
+                ],
+                "atomic_polyfill": [
+                    "dep:atomic_polyfill"
+                ],
+                "critical-section": [
+                    "critical_section",
+                    "atomic_polyfill"
+                ],
+                "critical_section": [
+                    "dep:critical_section"
+                ],
+                "default": [
+                    "std"
+                ],
+                "parking_lot": [
+                    "parking_lot_core"
+                ],
+                "parking_lot_core": [
+                    "dep:parking_lot_core"
+                ],
+                "race": [],
+                "std": [
+                    "alloc"
+                ],
+                "unstable": []
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/once_cell-1.17.1/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "all-features": true
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "Aleksey Kladov <aleksey.kladov@gmail.com>"
+            ],
+            "categories": [
+                "rust-patterns",
+                "memory-management"
+            ],
+            "keywords": [
+                "lazy",
+                "static"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/matklad/once_cell",
+            "homepage": null,
+            "documentation": "https://docs.rs/once_cell",
+            "edition": "2021",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.56"
+        },
+        {
+            "name": "pcre2",
+            "version": "0.2.3",
+            "id": "pcre2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "Unlicense/MIT",
+            "license_file": null,
+            "description": "High level wrapper library for PCRE2.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "libc",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2.46",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "log",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.4.5",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "pcre2-sys",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "thread_local",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "pcre2",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/pcre2-0.2.3/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/pcre2-0.2.3/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>"
+            ],
+            "categories": [
+                "text-processing"
+            ],
+            "keywords": [
+                "pcre",
+                "pcre2",
+                "regex",
+                "jit",
+                "perl"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/BurntSushi/rust-pcre2",
+            "homepage": "https://github.com/BurntSushi/rust-pcre2",
+            "documentation": "https://docs.rs/pcre2",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "pcre2-sys",
+            "version": "0.2.5",
+            "id": "pcre2-sys 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "Unlicense/MIT",
+            "license_file": null,
+            "description": "Low level bindings to PCRE2.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "libc",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "cc",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "build",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [
+                        "parallel"
+                    ],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "pkg-config",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3.13",
+                    "kind": "build",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "pcre2-sys",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/pcre2-sys-0.2.5/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "custom-build"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "build-script-build",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/pcre2-sys-0.2.5/build.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/pcre2-sys-0.2.5/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>"
+            ],
+            "categories": [
+                "external-ffi-bindings"
+            ],
+            "keywords": [
+                "pcre",
+                "pcre2",
+                "regex",
+                "jit"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/BurntSushi/rust-pcre2",
+            "homepage": "https://github.com/BurntSushi/rust-pcre2",
+            "documentation": "https://docs.rs/pcre2-sys",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "pkg-config",
+            "version": "0.3.26",
+            "id": "pkg-config 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "A library to run the pkg-config system tool at build time in order to be used in\nCargo build scripts.\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "lazy_static",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "pkg-config",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/pkg-config-0.3.26/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/pkg-config-0.3.26/tests/test.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/pkg-config-0.3.26/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Alex Crichton <alex@alexcrichton.com>"
+            ],
+            "categories": [],
+            "keywords": [
+                "build-dependencies"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/rust-lang/pkg-config-rs",
+            "homepage": null,
+            "documentation": "https://docs.rs/pkg-config",
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "proc-macro2",
+            "version": "1.0.56",
+            "id": "proc-macro2 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "A substitute implementation of the compiler's `proc_macro` API to decouple token-based libraries from the procedural macro use case.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "unicode-ident",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "quote",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rustversion",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "proc-macro2",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/proc-macro2-1.0.56/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "comments",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/proc-macro2-1.0.56/tests/comments.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "features",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/proc-macro2-1.0.56/tests/features.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "marker",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/proc-macro2-1.0.56/tests/marker.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/proc-macro2-1.0.56/tests/test.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_fmt",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/proc-macro2-1.0.56/tests/test_fmt.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_size",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/proc-macro2-1.0.56/tests/test_size.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "custom-build"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "build-script-build",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/proc-macro2-1.0.56/build.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "default": [
+                    "proc-macro"
+                ],
+                "nightly": [],
+                "proc-macro": [],
+                "span-locations": []
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/proc-macro2-1.0.56/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "rustc-args": [
+                            "--cfg",
+                            "procmacro2_semver_exempt"
+                        ],
+                        "rustdoc-args": [
+                            "--cfg",
+                            "procmacro2_semver_exempt",
+                            "--cfg",
+                            "doc_cfg"
+                        ],
+                        "targets": [
+                            "x86_64-unknown-linux-gnu"
+                        ]
+                    }
+                },
+                "playground": {
+                    "features": [
+                        "span-locations"
+                    ]
+                }
+            },
+            "publish": null,
+            "authors": [
+                "David Tolnay <dtolnay@gmail.com>",
+                "Alex Crichton <alex@alexcrichton.com>"
+            ],
+            "categories": [
+                "development-tools::procedural-macro-helpers"
+            ],
+            "keywords": [
+                "macros",
+                "syn"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/dtolnay/proc-macro2",
+            "homepage": null,
+            "documentation": "https://docs.rs/proc-macro2",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.31"
+        },
+        {
+            "name": "quote",
+            "version": "1.0.26",
+            "id": "quote 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "Quasi-quoting macro quote!(...)",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "proc-macro2",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.52",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rustversion",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "trybuild",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.66",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [
+                        "diff"
+                    ],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "quote",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/quote-1.0.26/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "compiletest",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/quote-1.0.26/tests/compiletest.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/quote-1.0.26/tests/test.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "custom-build"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "build-script-build",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/quote-1.0.26/build.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "default": [
+                    "proc-macro"
+                ],
+                "proc-macro": [
+                    "proc-macro2/proc-macro"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/quote-1.0.26/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "targets": [
+                            "x86_64-unknown-linux-gnu"
+                        ]
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "David Tolnay <dtolnay@gmail.com>"
+            ],
+            "categories": [
+                "development-tools::procedural-macro-helpers"
+            ],
+            "keywords": [
+                "macros",
+                "syn"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/dtolnay/quote",
+            "homepage": null,
+            "documentation": "https://docs.rs/quote/",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.31"
+        },
+        {
+            "name": "regex",
+            "version": "1.8.1",
+            "id": "regex 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "An implementation of regular expressions for Rust. This implementation uses\nfinite automata and guarantees linear time matching on all inputs.\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "aho-corasick",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "memchr",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^2.5.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "regex-syntax",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.7.1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "lazy_static",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "quickcheck",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.3",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rand",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.8.3",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [
+                        "getrandom",
+                        "small_rng"
+                    ],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "regex",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/src/lib.rs",
+                    "edition": "2021",
+                    "doc": true,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "shootout-regex-dna-bytes",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/examples/shootout-regex-dna-bytes.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "shootout-regex-dna-cheat",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/examples/shootout-regex-dna-cheat.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "shootout-regex-dna-replace",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/examples/shootout-regex-dna-replace.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "shootout-regex-dna-single-cheat",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/examples/shootout-regex-dna-single-cheat.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "shootout-regex-dna-single",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/examples/shootout-regex-dna-single.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "shootout-regex-dna",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/examples/shootout-regex-dna.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "default",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/tests/test_default.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "default-bytes",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/tests/test_default_bytes.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "nfa",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/tests/test_nfa.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "nfa-utf8bytes",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/tests/test_nfa_utf8bytes.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "nfa-bytes",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/tests/test_nfa_bytes.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "backtrack",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/tests/test_backtrack.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "backtrack-utf8bytes",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/tests/test_backtrack_utf8bytes.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "backtrack-bytes",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/tests/test_backtrack_bytes.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "crates-regex",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/tests/test_crates_regex.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                }
+            ],
+            "features": {
+                "aho-corasick": [
+                    "dep:aho-corasick"
+                ],
+                "default": [
+                    "std",
+                    "perf",
+                    "unicode",
+                    "regex-syntax/default"
+                ],
+                "memchr": [
+                    "dep:memchr"
+                ],
+                "pattern": [],
+                "perf": [
+                    "perf-cache",
+                    "perf-dfa",
+                    "perf-inline",
+                    "perf-literal"
+                ],
+                "perf-cache": [],
+                "perf-dfa": [],
+                "perf-inline": [],
+                "perf-literal": [
+                    "aho-corasick",
+                    "memchr"
+                ],
+                "std": [],
+                "unicode": [
+                    "unicode-age",
+                    "unicode-bool",
+                    "unicode-case",
+                    "unicode-gencat",
+                    "unicode-perl",
+                    "unicode-script",
+                    "unicode-segment",
+                    "regex-syntax/unicode"
+                ],
+                "unicode-age": [
+                    "regex-syntax/unicode-age"
+                ],
+                "unicode-bool": [
+                    "regex-syntax/unicode-bool"
+                ],
+                "unicode-case": [
+                    "regex-syntax/unicode-case"
+                ],
+                "unicode-gencat": [
+                    "regex-syntax/unicode-gencat"
+                ],
+                "unicode-perl": [
+                    "regex-syntax/unicode-perl"
+                ],
+                "unicode-script": [
+                    "regex-syntax/unicode-script"
+                ],
+                "unicode-segment": [
+                    "regex-syntax/unicode-segment"
+                ],
+                "unstable": [
+                    "pattern"
+                ],
+                "use_std": [
+                    "std"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-1.8.1/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "The Rust Project Developers"
+            ],
+            "categories": [
+                "text-processing"
+            ],
+            "keywords": [],
+            "readme": "README.md",
+            "repository": "https://github.com/rust-lang/regex",
+            "homepage": "https://github.com/rust-lang/regex",
+            "documentation": "https://docs.rs/regex",
+            "edition": "2021",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.60.0"
+        },
+        {
+            "name": "regex-automata",
+            "version": "0.1.10",
+            "id": "regex-automata 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "Unlicense/MIT",
+            "license_file": null,
+            "description": "Automata construction and matching using regular expressions.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "fst",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.4.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "regex-syntax",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.6.16",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "bstr",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [
+                        "std"
+                    ],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "lazy_static",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.2.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "regex",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.82",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde_bytes",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.11",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde_derive",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.82",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "toml",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.4.10",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "regex-automata",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-automata-0.1.10/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "default",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-automata-0.1.10/tests/tests.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                }
+            ],
+            "features": {
+                "default": [
+                    "std"
+                ],
+                "fst": [
+                    "dep:fst"
+                ],
+                "regex-syntax": [
+                    "dep:regex-syntax"
+                ],
+                "std": [
+                    "regex-syntax"
+                ],
+                "transducer": [
+                    "std",
+                    "fst"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-automata-0.1.10/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>"
+            ],
+            "categories": [
+                "text-processing"
+            ],
+            "keywords": [
+                "regex",
+                "dfa",
+                "automata",
+                "automaton",
+                "nfa"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/BurntSushi/regex-automata",
+            "homepage": "https://github.com/BurntSushi/regex-automata",
+            "documentation": "https://docs.rs/regex-automata",
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "regex-syntax",
+            "version": "0.6.29",
+            "id": "regex-syntax 0.6.29 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "A regular expression parser.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "regex-syntax",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-syntax-0.6.29/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bench"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "bench",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-syntax-0.6.29/benches/bench.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "default": [
+                    "unicode"
+                ],
+                "unicode": [
+                    "unicode-age",
+                    "unicode-bool",
+                    "unicode-case",
+                    "unicode-gencat",
+                    "unicode-perl",
+                    "unicode-script",
+                    "unicode-segment"
+                ],
+                "unicode-age": [],
+                "unicode-bool": [],
+                "unicode-case": [],
+                "unicode-gencat": [],
+                "unicode-perl": [],
+                "unicode-script": [],
+                "unicode-segment": []
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-syntax-0.6.29/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "The Rust Project Developers"
+            ],
+            "categories": [],
+            "keywords": [],
+            "readme": "README.md",
+            "repository": "https://github.com/rust-lang/regex",
+            "homepage": "https://github.com/rust-lang/regex",
+            "documentation": "https://docs.rs/regex-syntax",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "regex-syntax",
+            "version": "0.7.1",
+            "id": "regex-syntax 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "A regular expression parser.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "regex-syntax",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-syntax-0.7.1/src/lib.rs",
+                    "edition": "2021",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bench"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "bench",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-syntax-0.7.1/benches/bench.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "default": [
+                    "std",
+                    "unicode"
+                ],
+                "std": [],
+                "unicode": [
+                    "unicode-age",
+                    "unicode-bool",
+                    "unicode-case",
+                    "unicode-gencat",
+                    "unicode-perl",
+                    "unicode-script",
+                    "unicode-segment"
+                ],
+                "unicode-age": [],
+                "unicode-bool": [],
+                "unicode-case": [],
+                "unicode-gencat": [],
+                "unicode-perl": [],
+                "unicode-script": [],
+                "unicode-segment": []
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/regex-syntax-0.7.1/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "all-features": true,
+                        "rustdoc-args": [
+                            "--cfg",
+                            "docsrs"
+                        ]
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "The Rust Project Developers"
+            ],
+            "categories": [],
+            "keywords": [],
+            "readme": "README.md",
+            "repository": "https://github.com/rust-lang/regex",
+            "homepage": "https://github.com/rust-lang/regex",
+            "documentation": "https://docs.rs/regex-syntax",
+            "edition": "2021",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.60.0"
+        },
+        {
+            "name": "ripgrep",
+            "version": "13.0.0",
+            "id": "ripgrep 13.0.0 (path+file:///$ROOT$ripgrep)",
+            "license": "Unlicense OR MIT",
+            "license_file": null,
+            "description": "ripgrep is a line-oriented search tool that recursively searches the current\ndirectory for a regex pattern while respecting gitignore rules. ripgrep has\nfirst class support on Windows, macOS and Linux.\n",
+            "source": null,
+            "dependencies": [
+                {
+                    "name": "bstr",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.1.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "clap",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^2.33.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [
+                        "suggestions"
+                    ],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "grep",
+                    "source": null,
+                    "req": "^0.2.11",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null,
+                    "path": "$ROOT$ripgrep/crates/grep"
+                },
+                {
+                    "name": "ignore",
+                    "source": null,
+                    "req": "^0.4.19",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null,
+                    "path": "$ROOT$ripgrep/crates/ignore"
+                },
+                {
+                    "name": "lazy_static",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.1.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "log",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.4.5",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "regex",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.3.5",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde_json",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.23",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "termcolor",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.1.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.77",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde_derive",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.77",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "walkdir",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^2",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "clap",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^2.33.0",
+                    "kind": "build",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [
+                        "suggestions"
+                    ],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "lazy_static",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.1.0",
+                    "kind": "build",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "jemallocator",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.5.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": "cfg(all(target_env = \"musl\", target_pointer_width = \"64\"))",
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "bin"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "rg",
+                    "src_path": "$ROOT$ripgrep/crates/core/main.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "integration",
+                    "src_path": "$ROOT$ripgrep/tests/tests.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "custom-build"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "build-script-build",
+                    "src_path": "$ROOT$ripgrep/build.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "pcre2": [
+                    "grep/pcre2"
+                ],
+                "simd-accel": [
+                    "grep/simd-accel"
+                ]
+            },
+            "manifest_path": "$ROOT$ripgrep/Cargo.toml",
+            "metadata": {
+                "deb": {
+                    "assets": [
+                        [
+                            "target/release/rg",
+                            "usr/bin/",
+                            "755"
+                        ],
+                        [
+                            "COPYING",
+                            "usr/share/doc/ripgrep/",
+                            "644"
+                        ],
+                        [
+                            "LICENSE-MIT",
+                            "usr/share/doc/ripgrep/",
+                            "644"
+                        ],
+                        [
+                            "UNLICENSE",
+                            "usr/share/doc/ripgrep/",
+                            "644"
+                        ],
+                        [
+                            "CHANGELOG.md",
+                            "usr/share/doc/ripgrep/CHANGELOG",
+                            "644"
+                        ],
+                        [
+                            "README.md",
+                            "usr/share/doc/ripgrep/README",
+                            "644"
+                        ],
+                        [
+                            "FAQ.md",
+                            "usr/share/doc/ripgrep/FAQ",
+                            "644"
+                        ],
+                        [
+                            "deployment/deb/rg.1",
+                            "usr/share/man/man1/rg.1",
+                            "644"
+                        ],
+                        [
+                            "deployment/deb/rg.bash",
+                            "usr/share/bash-completion/completions/rg",
+                            "644"
+                        ],
+                        [
+                            "deployment/deb/rg.fish",
+                            "usr/share/fish/vendor_completions.d/rg.fish",
+                            "644"
+                        ],
+                        [
+                            "deployment/deb/_rg",
+                            "usr/share/zsh/vendor-completions/",
+                            "644"
+                        ]
+                    ],
+                    "extended-description": "ripgrep (rg) recursively searches your current directory for a regex pattern.\nBy default, ripgrep will respect your .gitignore and automatically skip hidden\nfiles/directories and binary files.\n",
+                    "features": [
+                        "pcre2"
+                    ],
+                    "section": "utils"
+                }
+            },
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>"
+            ],
+            "categories": [
+                "command-line-utilities",
+                "text-processing"
+            ],
+            "keywords": [
+                "regex",
+                "grep",
+                "egrep",
+                "search",
+                "pattern"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/BurntSushi/ripgrep",
+            "homepage": "https://github.com/BurntSushi/ripgrep",
+            "documentation": "https://github.com/BurntSushi/ripgrep",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.65"
+        },
+        {
+            "name": "ryu",
+            "version": "1.0.13",
+            "id": "ryu 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "Apache-2.0 OR BSL-1.0",
+            "license_file": null,
+            "description": "Fast floating point to string conversion",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "no-panic",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "num_cpus",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.8",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rand",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.8",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rand_xorshift",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "ryu",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/ryu-1.0.13/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "upstream_benchmark",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/ryu-1.0.13/examples/upstream_benchmark.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "common_test",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/ryu-1.0.13/tests/common_test.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "d2s_table_test",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/ryu-1.0.13/tests/d2s_table_test.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "d2s_test",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/ryu-1.0.13/tests/d2s_test.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "exhaustive",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/ryu-1.0.13/tests/exhaustive.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "f2s_test",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/ryu-1.0.13/tests/f2s_test.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "s2d_test",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/ryu-1.0.13/tests/s2d_test.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "s2f_test",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/ryu-1.0.13/tests/s2f_test.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bench"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "bench",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/ryu-1.0.13/benches/bench.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "no-panic": [
+                    "dep:no-panic"
+                ],
+                "small": []
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/ryu-1.0.13/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "targets": [
+                            "x86_64-unknown-linux-gnu"
+                        ]
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "David Tolnay <dtolnay@gmail.com>"
+            ],
+            "categories": [
+                "value-formatting",
+                "no-std"
+            ],
+            "keywords": [
+                "float"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/dtolnay/ryu",
+            "homepage": null,
+            "documentation": "https://docs.rs/ryu",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.36"
+        },
+        {
+            "name": "same-file",
+            "version": "1.0.6",
+            "id": "same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "Unlicense/MIT",
+            "license_file": null,
+            "description": "A simple crate for determining whether two file paths point to the same file.\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "doc-comment",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "winapi-util",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1.1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": "cfg(windows)",
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "same-file",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/same-file-1.0.6/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "is_same_file",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/same-file-1.0.6/examples/is_same_file.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "is_stderr",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/same-file-1.0.6/examples/is_stderr.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/same-file-1.0.6/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>"
+            ],
+            "categories": [],
+            "keywords": [
+                "same",
+                "file",
+                "equal",
+                "inode"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/BurntSushi/same-file",
+            "homepage": "https://github.com/BurntSushi/same-file",
+            "documentation": "https://docs.rs/same-file",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "serde",
+            "version": "1.0.160",
+            "id": "serde 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "A generic serialization/deserialization framework",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "serde_derive",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "=1.0.160",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde_derive",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "serde",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.160/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "custom-build"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "build-script-build",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.160/build.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "alloc": [],
+                "default": [
+                    "std"
+                ],
+                "derive": [
+                    "serde_derive"
+                ],
+                "rc": [],
+                "serde_derive": [
+                    "dep:serde_derive"
+                ],
+                "std": [],
+                "unstable": []
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde-1.0.160/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "features": [
+                            "derive"
+                        ],
+                        "targets": [
+                            "x86_64-unknown-linux-gnu"
+                        ]
+                    }
+                },
+                "playground": {
+                    "features": [
+                        "derive",
+                        "rc"
+                    ]
+                }
+            },
+            "publish": null,
+            "authors": [
+                "Erick Tryzelaar <erick.tryzelaar@gmail.com>",
+                "David Tolnay <dtolnay@gmail.com>"
+            ],
+            "categories": [
+                "encoding",
+                "no-std"
+            ],
+            "keywords": [
+                "serde",
+                "serialization",
+                "no_std"
+            ],
+            "readme": "crates-io.md",
+            "repository": "https://github.com/serde-rs/serde",
+            "homepage": "https://serde.rs",
+            "documentation": "https://docs.rs/serde",
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.19"
+        },
+        {
+            "name": "serde_derive",
+            "version": "1.0.160",
+            "id": "serde_derive 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "proc-macro2",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "quote",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "syn",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^2.0.3",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "proc-macro"
+                    ],
+                    "crate_types": [
+                        "proc-macro"
+                    ],
+                    "name": "serde_derive",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde_derive-1.0.160/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "custom-build"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "build-script-build",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde_derive-1.0.160/build.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "default": [],
+                "deserialize_in_place": []
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde_derive-1.0.160/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "targets": [
+                            "x86_64-unknown-linux-gnu"
+                        ]
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "Erick Tryzelaar <erick.tryzelaar@gmail.com>",
+                "David Tolnay <dtolnay@gmail.com>"
+            ],
+            "categories": [
+                "no-std"
+            ],
+            "keywords": [
+                "serde",
+                "serialization",
+                "no_std",
+                "derive"
+            ],
+            "readme": "crates-io.md",
+            "repository": "https://github.com/serde-rs/serde",
+            "homepage": "https://serde.rs",
+            "documentation": "https://serde.rs/derive.html",
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.56"
+        },
+        {
+            "name": "serde_json",
+            "version": "1.0.96",
+            "id": "serde_json 1.0.96 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "A JSON serialization file format",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "indexmap",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.5.2",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [
+                        "std"
+                    ],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "itoa",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "ryu",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.100",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "automod",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "indoc",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^2.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "ref-cast",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rustversion",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.100",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [
+                        "derive"
+                    ],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde_bytes",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.11",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde_derive",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "serde_stacker",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "trybuild",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.49",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [
+                        "diff"
+                    ],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "serde_json",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde_json-1.0.96/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "compiletest",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde_json-1.0.96/tests/compiletest.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "debug",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde_json-1.0.96/tests/debug.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "lexical",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde_json-1.0.96/tests/lexical.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "map",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde_json-1.0.96/tests/map.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "regression",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde_json-1.0.96/tests/regression.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "stream",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde_json-1.0.96/tests/stream.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde_json-1.0.96/tests/test.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "custom-build"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "build-script-build",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde_json-1.0.96/build.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "alloc": [
+                    "serde/alloc"
+                ],
+                "arbitrary_precision": [],
+                "default": [
+                    "std"
+                ],
+                "float_roundtrip": [],
+                "indexmap": [
+                    "dep:indexmap"
+                ],
+                "preserve_order": [
+                    "indexmap",
+                    "std"
+                ],
+                "raw_value": [],
+                "std": [
+                    "serde/std"
+                ],
+                "unbounded_depth": []
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/serde_json-1.0.96/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "features": [
+                            "raw_value",
+                            "unbounded_depth"
+                        ],
+                        "rustdoc-args": [
+                            "--cfg",
+                            "docsrs"
+                        ],
+                        "targets": [
+                            "x86_64-unknown-linux-gnu"
+                        ]
+                    }
+                },
+                "playground": {
+                    "features": [
+                        "raw_value"
+                    ]
+                }
+            },
+            "publish": null,
+            "authors": [
+                "Erick Tryzelaar <erick.tryzelaar@gmail.com>",
+                "David Tolnay <dtolnay@gmail.com>"
+            ],
+            "categories": [
+                "encoding",
+                "parser-implementations",
+                "no-std"
+            ],
+            "keywords": [
+                "json",
+                "serde",
+                "serialization"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/serde-rs/json",
+            "homepage": null,
+            "documentation": "https://docs.rs/serde_json",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.36"
+        },
+        {
+            "name": "strsim",
+            "version": "0.8.0",
+            "id": "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT",
+            "license_file": null,
+            "description": "Implementations of string similarity metrics.\nIncludes Hamming, Levenshtein, OSA, Damerau-Levenshtein, Jaro, and Jaro-Winkler.\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "strsim",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/strsim-0.8.0/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "lib",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/strsim-0.8.0/tests/lib.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bench"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "benches",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/strsim-0.8.0/benches/benches.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/strsim-0.8.0/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Danny Guo <dannyguo91@gmail.com>"
+            ],
+            "categories": [],
+            "keywords": [
+                "string",
+                "similarity",
+                "Hamming",
+                "Levenshtein",
+                "Jaro"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/dguo/strsim-rs",
+            "homepage": "https://github.com/dguo/strsim-rs",
+            "documentation": "https://docs.rs/strsim/",
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "syn",
+            "version": "2.0.15",
+            "id": "syn 2.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "Parser for Rust source code",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "proc-macro2",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.55",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "quote",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.25",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "unicode-ident",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "anyhow",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "automod",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "flate2",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "insta",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rayon",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "ref-cast",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "regex",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "reqwest",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.11",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [
+                        "blocking"
+                    ],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rustversion",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "syn-test-suite",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "tar",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.4.16",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "termcolor",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "walkdir",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^2.3.2",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "syn",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/src/lib.rs",
+                    "edition": "2021",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "regression",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/regression.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_asyncness",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_asyncness.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_attribute",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_attribute.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_derive_input",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_derive_input.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_expr",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_expr.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_generics",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_generics.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_grouping",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_grouping.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_ident",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_ident.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_item",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_item.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_iterators",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_iterators.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_lit",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_lit.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_meta",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_meta.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_parse_buffer",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_parse_buffer.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_parse_stream",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_parse_stream.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_pat",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_pat.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_path",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_path.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_precedence",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_precedence.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_receiver",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_receiver.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_round_trip",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_round_trip.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_shebang",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_shebang.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_should_parse",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_should_parse.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_size",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_size.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_stmt",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_stmt.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_token_trees",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_token_trees.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_ty",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_ty.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "test_visibility",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/test_visibility.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "zzz_stable",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/tests/zzz_stable.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bench"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "rust",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/benches/rust.rs",
+                    "edition": "2021",
+                    "required-features": [
+                        "full",
+                        "parsing"
+                    ],
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "bench"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "file",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/benches/file.rs",
+                    "edition": "2021",
+                    "required-features": [
+                        "full",
+                        "parsing"
+                    ],
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "clone-impls": [],
+                "default": [
+                    "derive",
+                    "parsing",
+                    "printing",
+                    "clone-impls",
+                    "proc-macro"
+                ],
+                "derive": [],
+                "extra-traits": [],
+                "fold": [],
+                "full": [],
+                "parsing": [],
+                "printing": [
+                    "quote"
+                ],
+                "proc-macro": [
+                    "proc-macro2/proc-macro",
+                    "quote/proc-macro"
+                ],
+                "quote": [
+                    "dep:quote"
+                ],
+                "test": [
+                    "syn-test-suite/all-features"
+                ],
+                "visit": [],
+                "visit-mut": []
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/syn-2.0.15/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "all-features": true,
+                        "rustdoc-args": [
+                            "--cfg",
+                            "doc_cfg"
+                        ],
+                        "targets": [
+                            "x86_64-unknown-linux-gnu"
+                        ]
+                    }
+                },
+                "playground": {
+                    "features": [
+                        "full",
+                        "visit",
+                        "visit-mut",
+                        "fold",
+                        "extra-traits"
+                    ]
+                }
+            },
+            "publish": null,
+            "authors": [
+                "David Tolnay <dtolnay@gmail.com>"
+            ],
+            "categories": [
+                "development-tools::procedural-macro-helpers",
+                "parser-implementations"
+            ],
+            "keywords": [
+                "macros",
+                "syn"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/dtolnay/syn",
+            "homepage": null,
+            "documentation": "https://docs.rs/syn",
+            "edition": "2021",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.56"
+        },
+        {
+            "name": "termcolor",
+            "version": "1.2.0",
+            "id": "termcolor 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "Unlicense OR MIT",
+            "license_file": null,
+            "description": "A simple cross platform library for writing colored text to a terminal.\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "winapi-util",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1.3",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": "cfg(windows)",
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "termcolor",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/termcolor-1.2.0/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/termcolor-1.2.0/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>"
+            ],
+            "categories": [],
+            "keywords": [
+                "windows",
+                "win",
+                "color",
+                "ansi",
+                "console"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/BurntSushi/termcolor",
+            "homepage": "https://github.com/BurntSushi/termcolor",
+            "documentation": "https://docs.rs/termcolor",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "textwrap",
+            "version": "0.11.0",
+            "id": "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT",
+            "license_file": null,
+            "description": "Textwrap is a small library for word wrapping, indenting, and\ndedenting strings.\n\nYou can use it to format strings (such as help and error messages) for\ndisplay in commandline applications. It is designed to be efficient\nand handle Unicode characters correctly.\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "hyphenation",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.7.1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [
+                        "embed_all"
+                    ],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "term_size",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "unicode-width",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1.3",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "lipsum",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.6",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rand",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.6",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rand_xorshift",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "version-sync",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.6",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "textwrap",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/textwrap-0.11.0/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "layout",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/textwrap-0.11.0/examples/layout.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "example"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "termwidth",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/textwrap-0.11.0/examples/termwidth.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "version-numbers",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/textwrap-0.11.0/tests/version-numbers.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bench"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "linear",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/textwrap-0.11.0/benches/linear.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "hyphenation": [
+                    "dep:hyphenation"
+                ],
+                "term_size": [
+                    "dep:term_size"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/textwrap-0.11.0/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "all-features": true
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "Martin Geisler <martin@geisler.net>"
+            ],
+            "categories": [
+                "text-processing",
+                "command-line-interface"
+            ],
+            "keywords": [
+                "text",
+                "formatting",
+                "wrap",
+                "typesetting",
+                "hyphenation"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/mgeisler/textwrap",
+            "homepage": null,
+            "documentation": "https://docs.rs/textwrap/",
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "thread_local",
+            "version": "1.1.7",
+            "id": "thread_local 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT OR Apache-2.0",
+            "license_file": null,
+            "description": "Per-object thread-local storage",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "cfg-if",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.0",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "once_cell",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.5.2",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "criterion",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.4.0",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "thread_local",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/thread_local-1.1.7/src/lib.rs",
+                    "edition": "2021",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bench"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "thread_local",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/thread_local-1.1.7/benches/thread_local.rs",
+                    "edition": "2021",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "nightly": []
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/thread_local-1.1.7/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Amanieu d'Antras <amanieu@gmail.com>"
+            ],
+            "categories": [],
+            "keywords": [
+                "thread_local",
+                "concurrent",
+                "thread"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/Amanieu/thread_local-rs",
+            "homepage": null,
+            "documentation": "https://docs.rs/thread_local/",
+            "edition": "2021",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "unicode-ident",
+            "version": "1.0.8",
+            "id": "unicode-ident 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "(MIT OR Apache-2.0) AND Unicode-DFS-2016",
+            "license_file": null,
+            "description": "Determine whether characters have the XID_Start or XID_Continue properties according to Unicode Standard Annex #31",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "criterion",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.4",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "fst",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.4",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rand",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.8",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [
+                        "small_rng"
+                    ],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "roaring",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.10",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "ucd-trie",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": false,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "unicode-xid",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.2.4",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "unicode-ident",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/unicode-ident-1.0.8/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "compare",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/unicode-ident-1.0.8/tests/compare.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "test"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "static_size",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/unicode-ident-1.0.8/tests/static_size.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "bench"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "xid",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/unicode-ident-1.0.8/benches/xid.rs",
+                    "edition": "2018",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/unicode-ident-1.0.8/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "targets": [
+                            "x86_64-unknown-linux-gnu"
+                        ]
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "David Tolnay <dtolnay@gmail.com>"
+            ],
+            "categories": [
+                "development-tools::procedural-macro-helpers",
+                "no-std"
+            ],
+            "keywords": [
+                "unicode",
+                "xid"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/dtolnay/unicode-ident",
+            "homepage": null,
+            "documentation": "https://docs.rs/unicode-ident",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": "1.31"
+        },
+        {
+            "name": "unicode-width",
+            "version": "0.1.10",
+            "id": "unicode-width 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT/Apache-2.0",
+            "license_file": null,
+            "description": "Determine displayed width of `char` and `str` types\naccording to Unicode Standard Annex #11 rules.\n",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "compiler_builtins",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rustc-std-workspace-core",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": null,
+                    "rename": "core",
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "rustc-std-workspace-std",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0",
+                    "kind": null,
+                    "rename": "std",
+                    "optional": true,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "unicode-width",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/unicode-width-0.1.10/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                }
+            ],
+            "features": {
+                "bench": [],
+                "compiler_builtins": [
+                    "dep:compiler_builtins"
+                ],
+                "core": [
+                    "dep:core"
+                ],
+                "default": [],
+                "no_std": [],
+                "rustc-dep-of-std": [
+                    "std",
+                    "core",
+                    "compiler_builtins"
+                ],
+                "std": [
+                    "dep:std"
+                ]
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/unicode-width-0.1.10/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "kwantam <kwantam@gmail.com>",
+                "Manish Goregaokar <manishsmail@gmail.com>"
+            ],
+            "categories": [],
+            "keywords": [
+                "text",
+                "width",
+                "unicode"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/unicode-rs/unicode-width",
+            "homepage": "https://github.com/unicode-rs/unicode-width",
+            "documentation": "https://unicode-rs.github.io/unicode-width",
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "walkdir",
+            "version": "2.3.3",
+            "id": "walkdir 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "Unlicense/MIT",
+            "license_file": null,
+            "description": "Recursively walk a directory.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "same-file",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^1.0.1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "doc-comment",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3",
+                    "kind": "dev",
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": null,
+                    "registry": null
+                },
+                {
+                    "name": "winapi-util",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.1.1",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": "cfg(windows)",
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "walkdir",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/walkdir-2.3.3/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/walkdir-2.3.3/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>"
+            ],
+            "categories": [
+                "filesystem"
+            ],
+            "keywords": [
+                "directory",
+                "recursive",
+                "walk",
+                "iterator"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/BurntSushi/walkdir",
+            "homepage": "https://github.com/BurntSushi/walkdir",
+            "documentation": "https://docs.rs/walkdir/",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "winapi",
+            "version": "0.3.9",
+            "id": "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT/Apache-2.0",
+            "license_file": null,
+            "description": "Raw FFI bindings for all of Windows API.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "winapi-i686-pc-windows-gnu",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.4",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": "i686-pc-windows-gnu",
+                    "registry": null
+                },
+                {
+                    "name": "winapi-x86_64-pc-windows-gnu",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.4",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [],
+                    "target": "x86_64-pc-windows-gnu",
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "winapi",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/winapi-0.3.9/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "custom-build"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "build-script-build",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/winapi-0.3.9/build.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {
+                "accctrl": [],
+                "aclapi": [],
+                "activation": [],
+                "adhoc": [],
+                "appmgmt": [],
+                "audioclient": [],
+                "audiosessiontypes": [],
+                "avrt": [],
+                "basetsd": [],
+                "bcrypt": [],
+                "bits": [],
+                "bits10_1": [],
+                "bits1_5": [],
+                "bits2_0": [],
+                "bits2_5": [],
+                "bits3_0": [],
+                "bits4_0": [],
+                "bits5_0": [],
+                "bitscfg": [],
+                "bitsmsg": [],
+                "bluetoothapis": [],
+                "bluetoothleapis": [],
+                "bthdef": [],
+                "bthioctl": [],
+                "bthledef": [],
+                "bthsdpdef": [],
+                "bugcodes": [],
+                "cderr": [],
+                "cfg": [],
+                "cfgmgr32": [],
+                "cguid": [],
+                "combaseapi": [],
+                "coml2api": [],
+                "commapi": [],
+                "commctrl": [],
+                "commdlg": [],
+                "commoncontrols": [],
+                "consoleapi": [],
+                "corecrt": [],
+                "corsym": [],
+                "d2d1": [],
+                "d2d1_1": [],
+                "d2d1_2": [],
+                "d2d1_3": [],
+                "d2d1effectauthor": [],
+                "d2d1effects": [],
+                "d2d1effects_1": [],
+                "d2d1effects_2": [],
+                "d2d1svg": [],
+                "d2dbasetypes": [],
+                "d3d": [],
+                "d3d10": [],
+                "d3d10_1": [],
+                "d3d10_1shader": [],
+                "d3d10effect": [],
+                "d3d10misc": [],
+                "d3d10sdklayers": [],
+                "d3d10shader": [],
+                "d3d11": [],
+                "d3d11_1": [],
+                "d3d11_2": [],
+                "d3d11_3": [],
+                "d3d11_4": [],
+                "d3d11on12": [],
+                "d3d11sdklayers": [],
+                "d3d11shader": [],
+                "d3d11tokenizedprogramformat": [],
+                "d3d12": [],
+                "d3d12sdklayers": [],
+                "d3d12shader": [],
+                "d3d9": [],
+                "d3d9caps": [],
+                "d3d9types": [],
+                "d3dcommon": [],
+                "d3dcompiler": [],
+                "d3dcsx": [],
+                "d3dkmdt": [],
+                "d3dkmthk": [],
+                "d3dukmdt": [],
+                "d3dx10core": [],
+                "d3dx10math": [],
+                "d3dx10mesh": [],
+                "datetimeapi": [],
+                "davclnt": [],
+                "dbghelp": [],
+                "dbt": [],
+                "dcommon": [],
+                "dcomp": [],
+                "dcompanimation": [],
+                "dcomptypes": [],
+                "dde": [],
+                "ddraw": [],
+                "ddrawi": [],
+                "ddrawint": [],
+                "debug": [
+                    "impl-debug"
+                ],
+                "debugapi": [],
+                "devguid": [],
+                "devicetopology": [],
+                "devpkey": [],
+                "devpropdef": [],
+                "dinput": [],
+                "dinputd": [],
+                "dispex": [],
+                "dmksctl": [],
+                "dmusicc": [],
+                "docobj": [],
+                "documenttarget": [],
+                "dot1x": [],
+                "dpa_dsa": [],
+                "dpapi": [],
+                "dsgetdc": [],
+                "dsound": [],
+                "dsrole": [],
+                "dvp": [],
+                "dwmapi": [],
+                "dwrite": [],
+                "dwrite_1": [],
+                "dwrite_2": [],
+                "dwrite_3": [],
+                "dxdiag": [],
+                "dxfile": [],
+                "dxgi": [],
+                "dxgi1_2": [],
+                "dxgi1_3": [],
+                "dxgi1_4": [],
+                "dxgi1_5": [],
+                "dxgi1_6": [],
+                "dxgidebug": [],
+                "dxgiformat": [],
+                "dxgitype": [],
+                "dxva2api": [],
+                "dxvahd": [],
+                "eaptypes": [],
+                "enclaveapi": [],
+                "endpointvolume": [],
+                "errhandlingapi": [],
+                "everything": [],
+                "evntcons": [],
+                "evntprov": [],
+                "evntrace": [],
+                "excpt": [],
+                "exdisp": [],
+                "fibersapi": [],
+                "fileapi": [],
+                "functiondiscoverykeys_devpkey": [],
+                "gl-gl": [],
+                "guiddef": [],
+                "handleapi": [],
+                "heapapi": [],
+                "hidclass": [],
+                "hidpi": [],
+                "hidsdi": [],
+                "hidusage": [],
+                "highlevelmonitorconfigurationapi": [],
+                "hstring": [],
+                "http": [],
+                "ifdef": [],
+                "ifmib": [],
+                "imm": [],
+                "impl-debug": [],
+                "impl-default": [],
+                "in6addr": [],
+                "inaddr": [],
+                "inspectable": [],
+                "interlockedapi": [],
+                "intsafe": [],
+                "ioapiset": [],
+                "ipexport": [],
+                "iphlpapi": [],
+                "ipifcons": [],
+                "ipmib": [],
+                "iprtrmib": [],
+                "iptypes": [],
+                "jobapi": [],
+                "jobapi2": [],
+                "knownfolders": [],
+                "ks": [],
+                "ksmedia": [],
+                "ktmtypes": [],
+                "ktmw32": [],
+                "l2cmn": [],
+                "libloaderapi": [],
+                "limits": [],
+                "lmaccess": [],
+                "lmalert": [],
+                "lmapibuf": [],
+                "lmat": [],
+                "lmcons": [],
+                "lmdfs": [],
+                "lmerrlog": [],
+                "lmjoin": [],
+                "lmmsg": [],
+                "lmremutl": [],
+                "lmrepl": [],
+                "lmserver": [],
+                "lmshare": [],
+                "lmstats": [],
+                "lmsvc": [],
+                "lmuse": [],
+                "lmwksta": [],
+                "lowlevelmonitorconfigurationapi": [],
+                "lsalookup": [],
+                "memoryapi": [],
+                "minschannel": [],
+                "minwinbase": [],
+                "minwindef": [],
+                "mmdeviceapi": [],
+                "mmeapi": [],
+                "mmreg": [],
+                "mmsystem": [],
+                "mprapidef": [],
+                "msaatext": [],
+                "mscat": [],
+                "mschapp": [],
+                "mssip": [],
+                "mstcpip": [],
+                "mswsock": [],
+                "mswsockdef": [],
+                "namedpipeapi": [],
+                "namespaceapi": [],
+                "nb30": [],
+                "ncrypt": [],
+                "netioapi": [],
+                "nldef": [],
+                "ntddndis": [],
+                "ntddscsi": [],
+                "ntddser": [],
+                "ntdef": [],
+                "ntlsa": [],
+                "ntsecapi": [],
+                "ntstatus": [],
+                "oaidl": [],
+                "objbase": [],
+                "objidl": [],
+                "objidlbase": [],
+                "ocidl": [],
+                "ole2": [],
+                "oleauto": [],
+                "olectl": [],
+                "oleidl": [],
+                "opmapi": [],
+                "pdh": [],
+                "perflib": [],
+                "physicalmonitorenumerationapi": [],
+                "playsoundapi": [],
+                "portabledevice": [],
+                "portabledeviceapi": [],
+                "portabledevicetypes": [],
+                "powerbase": [],
+                "powersetting": [],
+                "powrprof": [],
+                "processenv": [],
+                "processsnapshot": [],
+                "processthreadsapi": [],
+                "processtopologyapi": [],
+                "profileapi": [],
+                "propidl": [],
+                "propkey": [],
+                "propkeydef": [],
+                "propsys": [],
+                "prsht": [],
+                "psapi": [],
+                "qos": [],
+                "realtimeapiset": [],
+                "reason": [],
+                "restartmanager": [],
+                "restrictederrorinfo": [],
+                "rmxfguid": [],
+                "roapi": [],
+                "robuffer": [],
+                "roerrorapi": [],
+                "rpc": [],
+                "rpcdce": [],
+                "rpcndr": [],
+                "rtinfo": [],
+                "sapi": [],
+                "sapi51": [],
+                "sapi53": [],
+                "sapiddk": [],
+                "sapiddk51": [],
+                "schannel": [],
+                "sddl": [],
+                "securityappcontainer": [],
+                "securitybaseapi": [],
+                "servprov": [],
+                "setupapi": [],
+                "shellapi": [],
+                "shellscalingapi": [],
+                "shlobj": [],
+                "shobjidl": [],
+                "shobjidl_core": [],
+                "shtypes": [],
+                "softpub": [],
+                "spapidef": [],
+                "spellcheck": [],
+                "sporder": [],
+                "sql": [],
+                "sqlext": [],
+                "sqltypes": [],
+                "sqlucode": [],
+                "sspi": [],
+                "std": [],
+                "stralign": [],
+                "stringapiset": [],
+                "strmif": [],
+                "subauth": [],
+                "synchapi": [],
+                "sysinfoapi": [],
+                "systemtopologyapi": [],
+                "taskschd": [],
+                "tcpestats": [],
+                "tcpmib": [],
+                "textstor": [],
+                "threadpoolapiset": [],
+                "threadpoollegacyapiset": [],
+                "timeapi": [],
+                "timezoneapi": [],
+                "tlhelp32": [],
+                "transportsettingcommon": [],
+                "tvout": [],
+                "udpmib": [],
+                "unknwnbase": [],
+                "urlhist": [],
+                "urlmon": [],
+                "usb": [],
+                "usbioctl": [],
+                "usbiodef": [],
+                "usbscan": [],
+                "usbspec": [],
+                "userenv": [],
+                "usp10": [],
+                "utilapiset": [],
+                "uxtheme": [],
+                "vadefs": [],
+                "vcruntime": [],
+                "vsbackup": [],
+                "vss": [],
+                "vsserror": [],
+                "vswriter": [],
+                "wbemads": [],
+                "wbemcli": [],
+                "wbemdisp": [],
+                "wbemprov": [],
+                "wbemtran": [],
+                "wct": [],
+                "werapi": [],
+                "winbase": [],
+                "wincodec": [],
+                "wincodecsdk": [],
+                "wincon": [],
+                "wincontypes": [],
+                "wincred": [],
+                "wincrypt": [],
+                "windef": [],
+                "windot11": [],
+                "windowsceip": [],
+                "windowsx": [],
+                "winefs": [],
+                "winerror": [],
+                "winevt": [],
+                "wingdi": [],
+                "winhttp": [],
+                "wininet": [],
+                "winineti": [],
+                "winioctl": [],
+                "winnetwk": [],
+                "winnls": [],
+                "winnt": [],
+                "winreg": [],
+                "winsafer": [],
+                "winscard": [],
+                "winsmcrd": [],
+                "winsock2": [],
+                "winspool": [],
+                "winstring": [],
+                "winsvc": [],
+                "wintrust": [],
+                "winusb": [],
+                "winusbio": [],
+                "winuser": [],
+                "winver": [],
+                "wlanapi": [],
+                "wlanihv": [],
+                "wlanihvtypes": [],
+                "wlantypes": [],
+                "wlclient": [],
+                "wmistr": [],
+                "wnnc": [],
+                "wow64apiset": [],
+                "wpdmtpextensions": [],
+                "ws2bth": [],
+                "ws2def": [],
+                "ws2ipdef": [],
+                "ws2spi": [],
+                "ws2tcpip": [],
+                "wtsapi32": [],
+                "wtypes": [],
+                "wtypesbase": [],
+                "xinput": []
+            },
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/winapi-0.3.9/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "default-target": "x86_64-pc-windows-msvc",
+                        "features": [
+                            "everything",
+                            "impl-debug",
+                            "impl-default"
+                        ],
+                        "targets": [
+                            "aarch64-pc-windows-msvc",
+                            "i686-pc-windows-msvc",
+                            "x86_64-pc-windows-msvc"
+                        ]
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "Peter Atashian <retep998@gmail.com>"
+            ],
+            "categories": [
+                "external-ffi-bindings",
+                "no-std",
+                "os::windows-apis"
+            ],
+            "keywords": [
+                "windows",
+                "ffi",
+                "win32",
+                "com",
+                "directx"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/retep998/winapi-rs",
+            "homepage": null,
+            "documentation": "https://docs.rs/winapi/",
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "winapi-i686-pc-windows-gnu",
+            "version": "0.4.0",
+            "id": "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT/Apache-2.0",
+            "license_file": null,
+            "description": "Import libraries for the i686-pc-windows-gnu target. Please don't use this crate directly, depend on winapi instead.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "winapi-i686-pc-windows-gnu",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/winapi-i686-pc-windows-gnu-0.4.0/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "custom-build"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "build-script-build",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/winapi-i686-pc-windows-gnu-0.4.0/build.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/winapi-i686-pc-windows-gnu-0.4.0/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Peter Atashian <retep998@gmail.com>"
+            ],
+            "categories": [],
+            "keywords": [
+                "windows"
+            ],
+            "readme": null,
+            "repository": "https://github.com/retep998/winapi-rs",
+            "homepage": null,
+            "documentation": null,
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "winapi-util",
+            "version": "0.1.5",
+            "id": "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "Unlicense/MIT",
+            "license_file": null,
+            "description": "A dumping ground for high level safe wrappers over winapi.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [
+                {
+                    "name": "winapi",
+                    "source": "registry+https://github.com/rust-lang/crates.io-index",
+                    "req": "^0.3",
+                    "kind": null,
+                    "rename": null,
+                    "optional": false,
+                    "uses_default_features": true,
+                    "features": [
+                        "std",
+                        "consoleapi",
+                        "errhandlingapi",
+                        "fileapi",
+                        "minwindef",
+                        "processenv",
+                        "winbase",
+                        "wincon",
+                        "winerror",
+                        "winnt"
+                    ],
+                    "target": "cfg(windows)",
+                    "registry": null
+                }
+            ],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "winapi-util",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/winapi-util-0.1.5/src/lib.rs",
+                    "edition": "2018",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/winapi-util-0.1.5/Cargo.toml",
+            "metadata": {
+                "docs": {
+                    "rs": {
+                        "targets": [
+                            "x86_64-pc-windows-msvc"
+                        ]
+                    }
+                }
+            },
+            "publish": null,
+            "authors": [
+                "Andrew Gallant <jamslam@gmail.com>"
+            ],
+            "categories": [
+                "os::windows-apis",
+                "external-ffi-bindings"
+            ],
+            "keywords": [
+                "windows",
+                "winapi",
+                "util",
+                "win"
+            ],
+            "readme": "README.md",
+            "repository": "https://github.com/BurntSushi/winapi-util",
+            "homepage": "https://github.com/BurntSushi/winapi-util",
+            "documentation": "https://docs.rs/winapi-util",
+            "edition": "2018",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        },
+        {
+            "name": "winapi-x86_64-pc-windows-gnu",
+            "version": "0.4.0",
+            "id": "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+            "license": "MIT/Apache-2.0",
+            "license_file": null,
+            "description": "Import libraries for the x86_64-pc-windows-gnu target. Please don't use this crate directly, depend on winapi instead.",
+            "source": "registry+https://github.com/rust-lang/crates.io-index",
+            "dependencies": [],
+            "targets": [
+                {
+                    "kind": [
+                        "lib"
+                    ],
+                    "crate_types": [
+                        "lib"
+                    ],
+                    "name": "winapi-x86_64-pc-windows-gnu",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/winapi-x86_64-pc-windows-gnu-0.4.0/src/lib.rs",
+                    "edition": "2015",
+                    "doc": true,
+                    "doctest": true,
+                    "test": true
+                },
+                {
+                    "kind": [
+                        "custom-build"
+                    ],
+                    "crate_types": [
+                        "bin"
+                    ],
+                    "name": "build-script-build",
+                    "src_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/winapi-x86_64-pc-windows-gnu-0.4.0/build.rs",
+                    "edition": "2015",
+                    "doc": false,
+                    "doctest": false,
+                    "test": false
+                }
+            ],
+            "features": {},
+            "manifest_path": "$ROOT$.cargo/registry/src/index.crates.io-6f17d22bba15001f/winapi-x86_64-pc-windows-gnu-0.4.0/Cargo.toml",
+            "metadata": null,
+            "publish": null,
+            "authors": [
+                "Peter Atashian <retep998@gmail.com>"
+            ],
+            "categories": [],
+            "keywords": [
+                "windows"
+            ],
+            "readme": null,
+            "repository": "https://github.com/retep998/winapi-rs",
+            "homepage": null,
+            "documentation": null,
+            "edition": "2015",
+            "links": null,
+            "default_run": null,
+            "rust_version": null
+        }
+    ],
+    "workspace_members": [
+        "globset 0.4.10 (path+file:///$ROOT$ripgrep/crates/globset)",
+        "grep 0.2.11 (path+file:///$ROOT$ripgrep/crates/grep)",
+        "grep-cli 0.1.7 (path+file:///$ROOT$ripgrep/crates/cli)",
+        "grep-matcher 0.1.6 (path+file:///$ROOT$ripgrep/crates/matcher)",
+        "grep-pcre2 0.1.6 (path+file:///$ROOT$ripgrep/crates/pcre2)",
+        "grep-printer 0.1.7 (path+file:///$ROOT$ripgrep/crates/printer)",
+        "grep-searcher 0.1.11 (path+file:///$ROOT$ripgrep/crates/searcher)",
+        "grep-regex 0.1.11 (path+file:///$ROOT$ripgrep/crates/regex)",
+        "ignore 0.4.20 (path+file:///$ROOT$ripgrep/crates/ignore)",
+        "ripgrep 13.0.0 (path+file:///$ROOT$ripgrep)"
+    ],
+    "resolve": {
+        "nodes": [
+            {
+                "id": "aho-corasick 0.7.20 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "memchr",
+                        "pkg": "memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "default",
+                    "std"
+                ]
+            },
+            {
+                "id": "aho-corasick 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "memchr",
+                        "pkg": "memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "default",
+                    "perf-literal",
+                    "std"
+                ]
+            },
+            {
+                "id": "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "hermit-abi 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "hermit_abi",
+                        "pkg": "hermit-abi 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": "cfg(target_os = \"hermit\")"
+                            }
+                        ]
+                    },
+                    {
+                        "name": "libc",
+                        "pkg": "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": "cfg(unix)"
+                            }
+                        ]
+                    },
+                    {
+                        "name": "winapi",
+                        "pkg": "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": "cfg(windows)"
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "base64 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": [
+                    "default",
+                    "std"
+                ]
+            },
+            {
+                "id": "bitflags 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": [
+                    "default"
+                ]
+            },
+            {
+                "id": "bstr 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "once_cell 1.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "regex-automata 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "serde 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "memchr",
+                        "pkg": "memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "once_cell",
+                        "pkg": "once_cell 1.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "regex_automata",
+                        "pkg": "regex-automata 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "serde",
+                        "pkg": "serde 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "alloc",
+                    "default",
+                    "std",
+                    "unicode"
+                ]
+            },
+            {
+                "id": "bytecount 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": [
+                    "runtime-dispatch-simd"
+                ]
+            },
+            {
+                "id": "cc 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "jobserver 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "jobserver",
+                        "pkg": "jobserver 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "jobserver",
+                    "parallel"
+                ]
+            },
+            {
+                "id": "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": []
+            },
+            {
+                "id": "clap 2.34.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "bitflags 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "unicode-width 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "bitflags",
+                        "pkg": "bitflags 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "strsim",
+                        "pkg": "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "textwrap",
+                        "pkg": "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "unicode_width",
+                        "pkg": "unicode-width 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "strsim",
+                    "suggestions"
+                ]
+            },
+            {
+                "id": "crossbeam-channel 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "crossbeam-utils 0.8.15 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "cfg_if",
+                        "pkg": "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "crossbeam_utils",
+                        "pkg": "crossbeam-utils 0.8.15 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "crossbeam-utils",
+                    "default",
+                    "std"
+                ]
+            },
+            {
+                "id": "crossbeam-utils 0.8.15 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "cfg_if",
+                        "pkg": "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "std"
+                ]
+            },
+            {
+                "id": "encoding_rs 0.8.32 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "cfg_if",
+                        "pkg": "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "alloc",
+                    "default"
+                ]
+            },
+            {
+                "id": "encoding_rs_io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "encoding_rs 0.8.32 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "encoding_rs",
+                        "pkg": "encoding_rs 0.8.32 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": [
+                    "default",
+                    "std"
+                ]
+            },
+            {
+                "id": "glob 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": []
+            },
+            {
+                "id": "globset 0.4.10 (path+file:///$ROOT$ripgrep/crates/globset)",
+                "dependencies": [
+                    "aho-corasick 0.7.20 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "bstr 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "glob 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "log 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "regex 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "serde_json 1.0.96 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "aho_corasick",
+                        "pkg": "aho-corasick 0.7.20 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "bstr",
+                        "pkg": "bstr 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "fnv",
+                        "pkg": "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "glob",
+                        "pkg": "glob 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": "dev",
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "lazy_static",
+                        "pkg": "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": "dev",
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "log",
+                        "pkg": "log 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "regex",
+                        "pkg": "regex 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "serde_json",
+                        "pkg": "serde_json 1.0.96 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": "dev",
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "default",
+                    "log"
+                ]
+            },
+            {
+                "id": "grep 0.2.11 (path+file:///$ROOT$ripgrep/crates/grep)",
+                "dependencies": [
+                    "grep-cli 0.1.7 (path+file:///$ROOT$ripgrep/crates/cli)",
+                    "grep-matcher 0.1.6 (path+file:///$ROOT$ripgrep/crates/matcher)",
+                    "grep-printer 0.1.7 (path+file:///$ROOT$ripgrep/crates/printer)",
+                    "grep-regex 0.1.11 (path+file:///$ROOT$ripgrep/crates/regex)",
+                    "grep-searcher 0.1.11 (path+file:///$ROOT$ripgrep/crates/searcher)",
+                    "termcolor 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "walkdir 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "grep_cli",
+                        "pkg": "grep-cli 0.1.7 (path+file:///$ROOT$ripgrep/crates/cli)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "grep_matcher",
+                        "pkg": "grep-matcher 0.1.6 (path+file:///$ROOT$ripgrep/crates/matcher)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "grep_printer",
+                        "pkg": "grep-printer 0.1.7 (path+file:///$ROOT$ripgrep/crates/printer)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "grep_regex",
+                        "pkg": "grep-regex 0.1.11 (path+file:///$ROOT$ripgrep/crates/regex)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "grep_searcher",
+                        "pkg": "grep-searcher 0.1.11 (path+file:///$ROOT$ripgrep/crates/searcher)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "termcolor",
+                        "pkg": "termcolor 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": "dev",
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "walkdir",
+                        "pkg": "walkdir 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": "dev",
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "grep-cli 0.1.7 (path+file:///$ROOT$ripgrep/crates/cli)",
+                "dependencies": [
+                    "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "bstr 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "globset 0.4.10 (path+file:///$ROOT$ripgrep/crates/globset)",
+                    "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "log 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "regex 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "termcolor 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "atty",
+                        "pkg": "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "bstr",
+                        "pkg": "bstr 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "globset",
+                        "pkg": "globset 0.4.10 (path+file:///$ROOT$ripgrep/crates/globset)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "lazy_static",
+                        "pkg": "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "log",
+                        "pkg": "log 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "regex",
+                        "pkg": "regex 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "same_file",
+                        "pkg": "same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "termcolor",
+                        "pkg": "termcolor 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "winapi_util",
+                        "pkg": "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": "cfg(windows)"
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "grep-matcher 0.1.6 (path+file:///$ROOT$ripgrep/crates/matcher)",
+                "dependencies": [
+                    "memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "regex 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "memchr",
+                        "pkg": "memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "regex",
+                        "pkg": "regex 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": "dev",
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "grep-pcre2 0.1.6 (path+file:///$ROOT$ripgrep/crates/pcre2)",
+                "dependencies": [
+                    "grep-matcher 0.1.6 (path+file:///$ROOT$ripgrep/crates/matcher)",
+                    "pcre2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "grep_matcher",
+                        "pkg": "grep-matcher 0.1.6 (path+file:///$ROOT$ripgrep/crates/matcher)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "pcre2",
+                        "pkg": "pcre2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "grep-printer 0.1.7 (path+file:///$ROOT$ripgrep/crates/printer)",
+                "dependencies": [
+                    "base64 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "bstr 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "grep-matcher 0.1.6 (path+file:///$ROOT$ripgrep/crates/matcher)",
+                    "grep-regex 0.1.11 (path+file:///$ROOT$ripgrep/crates/regex)",
+                    "grep-searcher 0.1.11 (path+file:///$ROOT$ripgrep/crates/searcher)",
+                    "serde 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "serde_json 1.0.96 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "termcolor 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "base64",
+                        "pkg": "base64 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "bstr",
+                        "pkg": "bstr 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "grep_matcher",
+                        "pkg": "grep-matcher 0.1.6 (path+file:///$ROOT$ripgrep/crates/matcher)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "grep_regex",
+                        "pkg": "grep-regex 0.1.11 (path+file:///$ROOT$ripgrep/crates/regex)",
+                        "dep_kinds": [
+                            {
+                                "kind": "dev",
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "grep_searcher",
+                        "pkg": "grep-searcher 0.1.11 (path+file:///$ROOT$ripgrep/crates/searcher)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "serde",
+                        "pkg": "serde 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "serde_json",
+                        "pkg": "serde_json 1.0.96 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "termcolor",
+                        "pkg": "termcolor 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "base64",
+                    "default",
+                    "serde",
+                    "serde1",
+                    "serde_json"
+                ]
+            },
+            {
+                "id": "grep-regex 0.1.11 (path+file:///$ROOT$ripgrep/crates/regex)",
+                "dependencies": [
+                    "aho-corasick 0.7.20 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "bstr 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "grep-matcher 0.1.6 (path+file:///$ROOT$ripgrep/crates/matcher)",
+                    "log 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "regex 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "regex-syntax 0.6.29 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "thread_local 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "aho_corasick",
+                        "pkg": "aho-corasick 0.7.20 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "bstr",
+                        "pkg": "bstr 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "grep_matcher",
+                        "pkg": "grep-matcher 0.1.6 (path+file:///$ROOT$ripgrep/crates/matcher)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "log",
+                        "pkg": "log 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "regex",
+                        "pkg": "regex 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "regex_syntax",
+                        "pkg": "regex-syntax 0.6.29 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "thread_local",
+                        "pkg": "thread_local 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "grep-searcher 0.1.11 (path+file:///$ROOT$ripgrep/crates/searcher)",
+                "dependencies": [
+                    "bstr 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "bytecount 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "encoding_rs 0.8.32 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "encoding_rs_io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "grep-matcher 0.1.6 (path+file:///$ROOT$ripgrep/crates/matcher)",
+                    "grep-regex 0.1.11 (path+file:///$ROOT$ripgrep/crates/regex)",
+                    "log 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "memmap2 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "regex 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "bstr",
+                        "pkg": "bstr 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "bytecount",
+                        "pkg": "bytecount 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "encoding_rs",
+                        "pkg": "encoding_rs 0.8.32 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "encoding_rs_io",
+                        "pkg": "encoding_rs_io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "grep_matcher",
+                        "pkg": "grep-matcher 0.1.6 (path+file:///$ROOT$ripgrep/crates/matcher)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "grep_regex",
+                        "pkg": "grep-regex 0.1.11 (path+file:///$ROOT$ripgrep/crates/regex)",
+                        "dep_kinds": [
+                            {
+                                "kind": "dev",
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "log",
+                        "pkg": "log 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "memmap",
+                        "pkg": "memmap2 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "regex",
+                        "pkg": "regex 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": "dev",
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "default"
+                ]
+            },
+            {
+                "id": "hermit-abi 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "libc",
+                        "pkg": "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "default"
+                ]
+            },
+            {
+                "id": "ignore 0.4.20 (path+file:///$ROOT$ripgrep/crates/ignore)",
+                "dependencies": [
+                    "crossbeam-channel 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "globset 0.4.10 (path+file:///$ROOT$ripgrep/crates/globset)",
+                    "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "log 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "regex 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "thread_local 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "walkdir 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "crossbeam_channel",
+                        "pkg": "crossbeam-channel 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": "dev",
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "globset",
+                        "pkg": "globset 0.4.10 (path+file:///$ROOT$ripgrep/crates/globset)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "lazy_static",
+                        "pkg": "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "log",
+                        "pkg": "log 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "memchr",
+                        "pkg": "memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "regex",
+                        "pkg": "regex 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "same_file",
+                        "pkg": "same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "thread_local",
+                        "pkg": "thread_local 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "walkdir",
+                        "pkg": "walkdir 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "winapi_util",
+                        "pkg": "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": "cfg(windows)"
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "itoa 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": []
+            },
+            {
+                "id": "jemalloc-sys 0.5.3+5.3.0-patched (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "cc 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "cc",
+                        "pkg": "cc 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": "build",
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "libc",
+                        "pkg": "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "background_threads_runtime_support"
+                ]
+            },
+            {
+                "id": "jemallocator 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "jemalloc-sys 0.5.3+5.3.0-patched (registry+https://github.com/rust-lang/crates.io-index)",
+                    "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "jemalloc_sys",
+                        "pkg": "jemalloc-sys 0.5.3+5.3.0-patched (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "libc",
+                        "pkg": "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "background_threads_runtime_support",
+                    "default"
+                ]
+            },
+            {
+                "id": "jobserver 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "libc",
+                        "pkg": "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": "cfg(unix)"
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": []
+            },
+            {
+                "id": "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": [
+                    "default",
+                    "std"
+                ]
+            },
+            {
+                "id": "log 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "cfg_if",
+                        "pkg": "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": [
+                    "default",
+                    "std"
+                ]
+            },
+            {
+                "id": "memmap2 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "libc",
+                        "pkg": "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": "cfg(unix)"
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "once_cell 1.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": [
+                    "alloc",
+                    "default",
+                    "race",
+                    "std"
+                ]
+            },
+            {
+                "id": "pcre2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "log 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "pcre2-sys 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "thread_local 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "libc",
+                        "pkg": "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "log",
+                        "pkg": "log 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "pcre2_sys",
+                        "pkg": "pcre2-sys 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "thread_local",
+                        "pkg": "thread_local 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "pcre2-sys 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "cc 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "pkg-config 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "cc",
+                        "pkg": "cc 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": "build",
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "libc",
+                        "pkg": "libc 0.2.142 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "pkg_config",
+                        "pkg": "pkg-config 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": "build",
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "pkg-config 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": []
+            },
+            {
+                "id": "proc-macro2 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "unicode-ident 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "unicode_ident",
+                        "pkg": "unicode-ident 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "default",
+                    "proc-macro"
+                ]
+            },
+            {
+                "id": "quote 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "proc-macro2 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "proc_macro2",
+                        "pkg": "proc-macro2 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "default",
+                    "proc-macro"
+                ]
+            },
+            {
+                "id": "regex 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "aho-corasick 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "regex-syntax 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "aho_corasick",
+                        "pkg": "aho-corasick 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "memchr",
+                        "pkg": "memchr 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "regex_syntax",
+                        "pkg": "regex-syntax 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "aho-corasick",
+                    "default",
+                    "memchr",
+                    "perf",
+                    "perf-cache",
+                    "perf-dfa",
+                    "perf-inline",
+                    "perf-literal",
+                    "std",
+                    "unicode",
+                    "unicode-age",
+                    "unicode-bool",
+                    "unicode-case",
+                    "unicode-gencat",
+                    "unicode-perl",
+                    "unicode-script",
+                    "unicode-segment"
+                ]
+            },
+            {
+                "id": "regex-automata 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": []
+            },
+            {
+                "id": "regex-syntax 0.6.29 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": [
+                    "default",
+                    "unicode",
+                    "unicode-age",
+                    "unicode-bool",
+                    "unicode-case",
+                    "unicode-gencat",
+                    "unicode-perl",
+                    "unicode-script",
+                    "unicode-segment"
+                ]
+            },
+            {
+                "id": "regex-syntax 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": [
+                    "default",
+                    "std",
+                    "unicode",
+                    "unicode-age",
+                    "unicode-bool",
+                    "unicode-case",
+                    "unicode-gencat",
+                    "unicode-perl",
+                    "unicode-script",
+                    "unicode-segment"
+                ]
+            },
+            {
+                "id": "ripgrep 13.0.0 (path+file:///$ROOT$ripgrep)",
+                "dependencies": [
+                    "bstr 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "clap 2.34.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "grep 0.2.11 (path+file:///$ROOT$ripgrep/crates/grep)",
+                    "ignore 0.4.20 (path+file:///$ROOT$ripgrep/crates/ignore)",
+                    "jemallocator 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "log 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "regex 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "serde 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "serde_derive 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "serde_json 1.0.96 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "termcolor 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "walkdir 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "bstr",
+                        "pkg": "bstr 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "clap",
+                        "pkg": "clap 2.34.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            },
+                            {
+                                "kind": "build",
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "grep",
+                        "pkg": "grep 0.2.11 (path+file:///$ROOT$ripgrep/crates/grep)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "ignore",
+                        "pkg": "ignore 0.4.20 (path+file:///$ROOT$ripgrep/crates/ignore)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "jemallocator",
+                        "pkg": "jemallocator 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": "cfg(all(target_env = \"musl\", target_pointer_width = \"64\"))"
+                            }
+                        ]
+                    },
+                    {
+                        "name": "lazy_static",
+                        "pkg": "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            },
+                            {
+                                "kind": "build",
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "log",
+                        "pkg": "log 0.4.17 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "regex",
+                        "pkg": "regex 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "serde",
+                        "pkg": "serde 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": "dev",
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "serde_derive",
+                        "pkg": "serde_derive 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": "dev",
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "serde_json",
+                        "pkg": "serde_json 1.0.96 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "termcolor",
+                        "pkg": "termcolor 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "walkdir",
+                        "pkg": "walkdir 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": "dev",
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "ryu 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": []
+            },
+            {
+                "id": "same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "winapi_util",
+                        "pkg": "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": "cfg(windows)"
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "serde 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "serde_derive 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "serde_derive",
+                        "pkg": "serde_derive 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "alloc",
+                    "default",
+                    "derive",
+                    "serde_derive",
+                    "std"
+                ]
+            },
+            {
+                "id": "serde_derive 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "proc-macro2 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "quote 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "syn 2.0.15 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "proc_macro2",
+                        "pkg": "proc-macro2 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "quote",
+                        "pkg": "quote 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "syn",
+                        "pkg": "syn 2.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "default"
+                ]
+            },
+            {
+                "id": "serde_json 1.0.96 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "itoa 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "ryu 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "serde 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "itoa",
+                        "pkg": "itoa 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "ryu",
+                        "pkg": "ryu 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "serde",
+                        "pkg": "serde 1.0.160 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "default",
+                    "std"
+                ]
+            },
+            {
+                "id": "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": []
+            },
+            {
+                "id": "syn 2.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "proc-macro2 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "quote 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "unicode-ident 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "proc_macro2",
+                        "pkg": "proc-macro2 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "quote",
+                        "pkg": "quote 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "unicode_ident",
+                        "pkg": "unicode-ident 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "clone-impls",
+                    "default",
+                    "derive",
+                    "parsing",
+                    "printing",
+                    "proc-macro",
+                    "quote"
+                ]
+            },
+            {
+                "id": "termcolor 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "winapi_util",
+                        "pkg": "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": "cfg(windows)"
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "unicode-width 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "unicode_width",
+                        "pkg": "unicode-width 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "thread_local 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "once_cell 1.17.1 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "cfg_if",
+                        "pkg": "cfg-if 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "once_cell",
+                        "pkg": "once_cell 1.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "unicode-ident 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": []
+            },
+            {
+                "id": "unicode-width 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": [
+                    "default"
+                ]
+            },
+            {
+                "id": "walkdir 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "same_file",
+                        "pkg": "same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": null
+                            }
+                        ]
+                    },
+                    {
+                        "name": "winapi_util",
+                        "pkg": "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": "cfg(windows)"
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                    "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "winapi_i686_pc_windows_gnu",
+                        "pkg": "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": "i686-pc-windows-gnu"
+                            }
+                        ]
+                    },
+                    {
+                        "name": "winapi_x86_64_pc_windows_gnu",
+                        "pkg": "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": "x86_64-pc-windows-gnu"
+                            }
+                        ]
+                    }
+                ],
+                "features": [
+                    "consoleapi",
+                    "errhandlingapi",
+                    "fileapi",
+                    "minwinbase",
+                    "minwindef",
+                    "processenv",
+                    "std",
+                    "winbase",
+                    "wincon",
+                    "winerror",
+                    "winnt"
+                ]
+            },
+            {
+                "id": "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": []
+            },
+            {
+                "id": "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [
+                    "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)"
+                ],
+                "deps": [
+                    {
+                        "name": "winapi",
+                        "pkg": "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+                        "dep_kinds": [
+                            {
+                                "kind": null,
+                                "target": "cfg(windows)"
+                            }
+                        ]
+                    }
+                ],
+                "features": []
+            },
+            {
+                "id": "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+                "dependencies": [],
+                "deps": [],
+                "features": []
+            }
+        ],
+        "root": "ripgrep 13.0.0 (path+file:///$ROOT$ripgrep)"
+    },
+    "target_directory": "$ROOT$ripgrep/target",
+    "version": 1,
+    "workspace_root": "$ROOT$ripgrep",
+    "metadata": null
+}
diff --git a/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/src/query_group.rs b/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/src/query_group.rs
index 88db6093ee0..d761a5e798e 100644
--- a/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/src/query_group.rs
+++ b/src/tools/rust-analyzer/crates/ra-salsa/ra-salsa-macros/src/query_group.rs
@@ -242,7 +242,7 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
         let tracing = if let QueryStorage::Memoized | QueryStorage::LruMemoized = query.storage {
             let s = format!("{trait_name}::{fn_name}");
             Some(quote! {
-                let _p = tracing::debug_span!(#s, #(#key_names = tracing::field::debug(&#key_names)),*).entered();
+                let _p = tracing::trace_span!(#s, #(#key_names = tracing::field::debug(&#key_names)),*).entered();
             })
         } else {
             None
diff --git a/src/tools/rust-analyzer/crates/ra-salsa/src/derived/slot.rs b/src/tools/rust-analyzer/crates/ra-salsa/src/derived/slot.rs
index 6c5ccba173b..cfe2c48f411 100644
--- a/src/tools/rust-analyzer/crates/ra-salsa/src/derived/slot.rs
+++ b/src/tools/rust-analyzer/crates/ra-salsa/src/derived/slot.rs
@@ -13,7 +13,7 @@ use crate::{Database, DatabaseKeyIndex, Event, EventKind, QueryDb};
 use parking_lot::{RawRwLock, RwLock};
 use std::ops::Deref;
 use std::sync::atomic::{AtomicBool, Ordering};
-use tracing::{debug, info};
+use tracing::trace;
 
 pub(super) struct Slot<Q>
 where
@@ -126,7 +126,7 @@ where
         // doing any `set` invocations while the query function runs.
         let revision_now = runtime.current_revision();
 
-        info!("{:?}: invoked at {:?}", self, revision_now,);
+        trace!("{:?}: invoked at {:?}", self, revision_now,);
 
         // First, do a check with a read-lock.
         loop {
@@ -152,7 +152,7 @@ where
     ) -> StampedValue<Q::Value> {
         let runtime = db.salsa_runtime();
 
-        debug!("{:?}: read_upgrade(revision_now={:?})", self, revision_now,);
+        trace!("{:?}: read_upgrade(revision_now={:?})", self, revision_now,);
 
         // Check with an upgradable read to see if there is a value
         // already. (This permits other readers but prevents anyone
@@ -184,7 +184,7 @@ where
         // inputs and check whether they are out of date.
         if let Some(memo) = &mut old_memo {
             if let Some(value) = memo.verify_value(db.ops_database(), revision_now, &active_query) {
-                info!("{:?}: validated old memoized value", self,);
+                trace!("{:?}: validated old memoized value", self,);
 
                 db.salsa_event(Event {
                     runtime_id: runtime.id(),
@@ -212,7 +212,7 @@ where
         old_memo: Option<Memo<Q::Value>>,
         key: &Q::Key,
     ) -> StampedValue<Q::Value> {
-        tracing::info!("{:?}: executing query", self.database_key_index().debug(db));
+        tracing::trace!("{:?}: executing query", self.database_key_index().debug(db));
 
         db.salsa_event(Event {
             runtime_id: db.salsa_runtime().id(),
@@ -224,7 +224,7 @@ where
         let value = match Cycle::catch(|| Q::execute(db, key.clone())) {
             Ok(v) => v,
             Err(cycle) => {
-                tracing::debug!(
+                tracing::trace!(
                     "{:?}: caught cycle {:?}, have strategy {:?}",
                     self.database_key_index().debug(db),
                     cycle,
@@ -272,9 +272,10 @@ where
             // consumers must be aware of. Becoming *more* durable
             // is not. See the test `constant_to_non_constant`.
             if revisions.durability >= old_memo.revisions.durability && old_memo.value == value {
-                debug!(
+                trace!(
                     "read_upgrade({:?}): value is equal, back-dating to {:?}",
-                    self, old_memo.revisions.changed_at,
+                    self,
+                    old_memo.revisions.changed_at,
                 );
 
                 assert!(old_memo.revisions.changed_at <= revisions.changed_at);
@@ -290,7 +291,7 @@ where
 
         let memo_value = new_value.value.clone();
 
-        debug!("read_upgrade({:?}): result.revisions = {:#?}", self, revisions,);
+        trace!("read_upgrade({:?}): result.revisions = {:#?}", self, revisions,);
 
         panic_guard.proceed(Some(Memo { value: memo_value, verified_at: revision_now, revisions }));
 
@@ -339,9 +340,11 @@ where
             }
 
             QueryState::Memoized(memo) => {
-                debug!(
+                trace!(
                     "{:?}: found memoized value, verified_at={:?}, changed_at={:?}",
-                    self, memo.verified_at, memo.revisions.changed_at,
+                    self,
+                    memo.verified_at,
+                    memo.revisions.changed_at,
                 );
 
                 if memo.verified_at < revision_now {
@@ -355,7 +358,7 @@ where
                     value: value.clone(),
                 };
 
-                info!("{:?}: returning memoized value changed at {:?}", self, value.changed_at);
+                trace!("{:?}: returning memoized value changed at {:?}", self, value.changed_at);
 
                 ProbeState::UpToDate(value)
             }
@@ -387,7 +390,7 @@ where
     }
 
     pub(super) fn invalidate(&self, new_revision: Revision) -> Option<Durability> {
-        tracing::debug!("Slot::invalidate(new_revision = {:?})", new_revision);
+        tracing::trace!("Slot::invalidate(new_revision = {:?})", new_revision);
         match &mut *self.state.write() {
             QueryState::Memoized(memo) => {
                 memo.revisions.untracked = true;
@@ -411,9 +414,11 @@ where
 
         db.unwind_if_cancelled();
 
-        debug!(
+        trace!(
             "maybe_changed_after({:?}) called with revision={:?}, revision_now={:?}",
-            self, revision, revision_now,
+            self,
+            revision,
+            revision_now,
         );
 
         // Do an initial probe with just the read-lock.
@@ -680,9 +685,11 @@ where
         assert!(self.verified_at != revision_now);
         let verified_at = self.verified_at;
 
-        debug!(
+        trace!(
             "verify_revisions: verified_at={:?}, revision_now={:?}, inputs={:#?}",
-            verified_at, revision_now, self.revisions.inputs
+            verified_at,
+            revision_now,
+            self.revisions.inputs
         );
 
         if self.check_durability(db.salsa_runtime()) {
@@ -708,7 +715,7 @@ where
                 let changed_input =
                     inputs.slice.iter().find(|&&input| db.maybe_changed_after(input, verified_at));
                 if let Some(input) = changed_input {
-                    debug!("validate_memoized_value: `{:?}` may have changed", input);
+                    trace!("validate_memoized_value: `{:?}` may have changed", input);
 
                     return false;
                 }
@@ -721,7 +728,7 @@ where
     /// True if this memo is known not to have changed based on its durability.
     fn check_durability(&self, runtime: &Runtime) -> bool {
         let last_changed = runtime.last_changed_revision(self.revisions.durability);
-        debug!(
+        trace!(
             "check_durability(last_changed={:?} <= verified_at={:?}) = {:?}",
             last_changed,
             self.verified_at,
diff --git a/src/tools/rust-analyzer/crates/ra-salsa/src/derived_lru/slot.rs b/src/tools/rust-analyzer/crates/ra-salsa/src/derived_lru/slot.rs
index ff9cc4eade2..73a5e07aa05 100644
--- a/src/tools/rust-analyzer/crates/ra-salsa/src/derived_lru/slot.rs
+++ b/src/tools/rust-analyzer/crates/ra-salsa/src/derived_lru/slot.rs
@@ -17,7 +17,7 @@ use parking_lot::{RawRwLock, RwLock};
 use std::marker::PhantomData;
 use std::ops::Deref;
 use std::sync::atomic::{AtomicBool, Ordering};
-use tracing::{debug, info};
+use tracing::trace;
 
 pub(super) struct Slot<Q, MP>
 where
@@ -140,7 +140,7 @@ where
         // doing any `set` invocations while the query function runs.
         let revision_now = runtime.current_revision();
 
-        info!("{:?}: invoked at {:?}", self, revision_now,);
+        trace!("{:?}: invoked at {:?}", self, revision_now,);
 
         // First, do a check with a read-lock.
         loop {
@@ -168,7 +168,7 @@ where
     ) -> StampedValue<Q::Value> {
         let runtime = db.salsa_runtime();
 
-        debug!("{:?}: read_upgrade(revision_now={:?})", self, revision_now,);
+        trace!("{:?}: read_upgrade(revision_now={:?})", self, revision_now,);
 
         // Check with an upgradable read to see if there is a value
         // already. (This permits other readers but prevents anyone
@@ -202,7 +202,7 @@ where
         // inputs and check whether they are out of date.
         if let Some(memo) = &mut old_memo {
             if let Some(value) = memo.verify_value(db.ops_database(), revision_now, &active_query) {
-                info!("{:?}: validated old memoized value", self,);
+                trace!("{:?}: validated old memoized value", self,);
 
                 db.salsa_event(Event {
                     runtime_id: runtime.id(),
@@ -230,7 +230,7 @@ where
         old_memo: Option<Memo<Q::Value>>,
         key: &Q::Key,
     ) -> StampedValue<Q::Value> {
-        tracing::info!("{:?}: executing query", self.database_key_index().debug(db));
+        tracing::trace!("{:?}: executing query", self.database_key_index().debug(db));
 
         db.salsa_event(Event {
             runtime_id: db.salsa_runtime().id(),
@@ -242,7 +242,7 @@ where
         let value = match Cycle::catch(|| Q::execute(db, key.clone())) {
             Ok(v) => v,
             Err(cycle) => {
-                tracing::debug!(
+                tracing::trace!(
                     "{:?}: caught cycle {:?}, have strategy {:?}",
                     self.database_key_index().debug(db),
                     cycle,
@@ -293,9 +293,10 @@ where
                 if revisions.durability >= old_memo.revisions.durability
                     && MP::memoized_value_eq(old_value, &value)
                 {
-                    debug!(
+                    trace!(
                         "read_upgrade({:?}): value is equal, back-dating to {:?}",
-                        self, old_memo.revisions.changed_at,
+                        self,
+                        old_memo.revisions.changed_at,
                     );
 
                     assert!(old_memo.revisions.changed_at <= revisions.changed_at);
@@ -313,7 +314,7 @@ where
         let memo_value =
             if self.should_memoize_value(key) { Some(new_value.value.clone()) } else { None };
 
-        debug!("read_upgrade({:?}): result.revisions = {:#?}", self, revisions,);
+        trace!("read_upgrade({:?}): result.revisions = {:#?}", self, revisions,);
 
         panic_guard.proceed(Some(Memo { value: memo_value, verified_at: revision_now, revisions }));
 
@@ -362,9 +363,11 @@ where
             }
 
             QueryState::Memoized(memo) => {
-                debug!(
+                trace!(
                     "{:?}: found memoized value, verified_at={:?}, changed_at={:?}",
-                    self, memo.verified_at, memo.revisions.changed_at,
+                    self,
+                    memo.verified_at,
+                    memo.revisions.changed_at,
                 );
 
                 if memo.verified_at < revision_now {
@@ -378,7 +381,11 @@ where
                         value: value.clone(),
                     };
 
-                    info!("{:?}: returning memoized value changed at {:?}", self, value.changed_at);
+                    trace!(
+                        "{:?}: returning memoized value changed at {:?}",
+                        self,
+                        value.changed_at
+                    );
 
                     ProbeState::UpToDate(value)
                 } else {
@@ -426,7 +433,7 @@ where
     }
 
     pub(super) fn invalidate(&self, new_revision: Revision) -> Option<Durability> {
-        tracing::debug!("Slot::invalidate(new_revision = {:?})", new_revision);
+        tracing::trace!("Slot::invalidate(new_revision = {:?})", new_revision);
         match &mut *self.state.write() {
             QueryState::Memoized(memo) => {
                 memo.revisions.untracked = true;
@@ -450,9 +457,11 @@ where
 
         db.unwind_if_cancelled();
 
-        debug!(
+        trace!(
             "maybe_changed_after({:?}) called with revision={:?}, revision_now={:?}",
-            self, revision, revision_now,
+            self,
+            revision,
+            revision_now,
         );
 
         // Do an initial probe with just the read-lock.
@@ -734,9 +743,11 @@ where
         assert!(self.verified_at != revision_now);
         let verified_at = self.verified_at;
 
-        debug!(
+        trace!(
             "verify_revisions: verified_at={:?}, revision_now={:?}, inputs={:#?}",
-            verified_at, revision_now, self.revisions.inputs
+            verified_at,
+            revision_now,
+            self.revisions.inputs
         );
 
         if self.check_durability(db.salsa_runtime()) {
@@ -762,7 +773,7 @@ where
                 let changed_input =
                     inputs.slice.iter().find(|&&input| db.maybe_changed_after(input, verified_at));
                 if let Some(input) = changed_input {
-                    debug!("validate_memoized_value: `{:?}` may have changed", input);
+                    trace!("validate_memoized_value: `{:?}` may have changed", input);
 
                     return false;
                 }
@@ -775,7 +786,7 @@ where
     /// True if this memo is known not to have changed based on its durability.
     fn check_durability(&self, runtime: &Runtime) -> bool {
         let last_changed = runtime.last_changed_revision(self.revisions.durability);
-        debug!(
+        trace!(
             "check_durability(last_changed={:?} <= verified_at={:?}) = {:?}",
             last_changed,
             self.verified_at,
diff --git a/src/tools/rust-analyzer/crates/ra-salsa/src/input.rs b/src/tools/rust-analyzer/crates/ra-salsa/src/input.rs
index f04f48e3bab..4992a0c7271 100644
--- a/src/tools/rust-analyzer/crates/ra-salsa/src/input.rs
+++ b/src/tools/rust-analyzer/crates/ra-salsa/src/input.rs
@@ -14,7 +14,7 @@ use crate::{DatabaseKeyIndex, QueryDb};
 use indexmap::map::Entry;
 use parking_lot::RwLock;
 use std::iter;
-use tracing::debug;
+use tracing::trace;
 
 /// Input queries store the result plus a list of the other queries
 /// that they invoked. This means we can avoid recomputing them when
@@ -73,11 +73,11 @@ where
             return true;
         };
 
-        debug!("maybe_changed_after(slot={:?}, revision={:?})", Q::default(), revision,);
+        trace!("maybe_changed_after(slot={:?}, revision={:?})", Q::default(), revision,);
 
         let changed_at = slot.stamped_value.read().changed_at;
 
-        debug!("maybe_changed_after: changed_at = {:?}", changed_at);
+        trace!("maybe_changed_after: changed_at = {:?}", changed_at);
 
         changed_at > revision
     }
@@ -140,7 +140,7 @@ where
     Q: Query,
 {
     fn set(&self, runtime: &mut Runtime, key: &Q::Key, value: Q::Value, durability: Durability) {
-        tracing::debug!("{:?}({:?}) = {:?} ({:?})", Q::default(), key, value, durability);
+        tracing::trace!("{:?}({:?}) = {:?} ({:?})", Q::default(), key, value, durability);
 
         // The value is changing, so we need a new revision (*). We also
         // need to update the 'last changed' revision by invoking
@@ -234,14 +234,14 @@ where
     ) -> bool {
         debug_assert!(revision < db.salsa_runtime().current_revision());
 
-        debug!("maybe_changed_after(slot={:?}, revision={:?})", Q::default(), revision,);
+        trace!("maybe_changed_after(slot={:?}, revision={:?})", Q::default(), revision,);
 
         let Some(value) = &*self.slot.stamped_value.read() else {
             return true;
         };
         let changed_at = value.changed_at;
 
-        debug!("maybe_changed_after: changed_at = {:?}", changed_at);
+        trace!("maybe_changed_after: changed_at = {:?}", changed_at);
 
         changed_at > revision
     }
@@ -298,7 +298,7 @@ where
     Q: Query<Key = ()>,
 {
     fn set(&self, runtime: &mut Runtime, (): &Q::Key, value: Q::Value, durability: Durability) {
-        tracing::debug!("{:?} = {:?} ({:?})", Q::default(), value, durability);
+        tracing::trace!("{:?} = {:?} ({:?})", Q::default(), value, durability);
 
         // The value is changing, so we need a new revision (*). We also
         // need to update the 'last changed' revision by invoking
diff --git a/src/tools/rust-analyzer/crates/ra-salsa/src/lib.rs b/src/tools/rust-analyzer/crates/ra-salsa/src/lib.rs
index 8530521d915..843b6d31f0c 100644
--- a/src/tools/rust-analyzer/crates/ra-salsa/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ra-salsa/src/lib.rs
@@ -79,7 +79,7 @@ pub trait Database: plumbing::DatabaseOps {
 
         let current_revision = runtime.current_revision();
         let pending_revision = runtime.pending_revision();
-        tracing::debug!(
+        tracing::trace!(
             "unwind_if_cancelled: current_revision={:?}, pending_revision={:?}",
             current_revision,
             pending_revision
@@ -684,7 +684,7 @@ impl Cycle {
     }
 
     pub(crate) fn throw(self) -> ! {
-        tracing::debug!("throwing cycle {:?}", self);
+        tracing::trace!("throwing cycle {:?}", self);
         std::panic::resume_unwind(Box::new(self))
     }
 
diff --git a/src/tools/rust-analyzer/crates/ra-salsa/src/lru.rs b/src/tools/rust-analyzer/crates/ra-salsa/src/lru.rs
index a6f96beeab1..7fbd42f9262 100644
--- a/src/tools/rust-analyzer/crates/ra-salsa/src/lru.rs
+++ b/src/tools/rust-analyzer/crates/ra-salsa/src/lru.rs
@@ -103,11 +103,11 @@ where
 
     /// Records that `node` was used. This may displace an old node (if the LRU limits are
     pub(crate) fn record_use(&self, node: &Arc<Node>) -> Option<Arc<Node>> {
-        tracing::debug!("record_use(node={:?})", node);
+        tracing::trace!("record_use(node={:?})", node);
 
         // Load green zone length and check if the LRU cache is even enabled.
         let green_zone = self.green_zone.load(Ordering::Acquire);
-        tracing::debug!("record_use: green_zone={}", green_zone);
+        tracing::trace!("record_use: green_zone={}", green_zone);
         if green_zone == 0 {
             return None;
         }
@@ -115,7 +115,7 @@ where
         // Find current index of list (if any) and the current length
         // of our green zone.
         let index = node.lru_index().load();
-        tracing::debug!("record_use: index={}", index);
+        tracing::trace!("record_use: index={}", index);
 
         // Already a member of the list, and in the green zone -- nothing to do!
         if index < green_zone {
@@ -162,9 +162,9 @@ where
         let entries =
             std::mem::replace(&mut self.entries, Vec::with_capacity(self.end_red_zone as usize));
 
-        tracing::debug!("green_zone = {:?}", self.green_zone());
-        tracing::debug!("yellow_zone = {:?}", self.yellow_zone());
-        tracing::debug!("red_zone = {:?}", self.red_zone());
+        tracing::trace!("green_zone = {:?}", self.green_zone());
+        tracing::trace!("yellow_zone = {:?}", self.yellow_zone());
+        tracing::trace!("red_zone = {:?}", self.red_zone());
 
         // We expect to resize when the LRU cache is basically empty.
         // So just forget all the old LRU indices to start.
@@ -180,7 +180,7 @@ where
     /// list may displace an old member of the red zone, in which case
     /// that is returned.
     fn record_use(&mut self, node: &Arc<Node>) -> Option<Arc<Node>> {
-        tracing::debug!("record_use(node={:?})", node);
+        tracing::trace!("record_use(node={:?})", node);
 
         // NB: When this is invoked, we have typically already loaded
         // the LRU index (to check if it is in green zone). But that
@@ -212,7 +212,7 @@ where
         if len < self.end_red_zone {
             self.entries.push(node.clone());
             node.lru_index().store(len);
-            tracing::debug!("inserted node {:?} at {}", node, len);
+            tracing::trace!("inserted node {:?} at {}", node, len);
             return self.record_use(node);
         }
 
@@ -220,7 +220,7 @@ where
         // zone and then promoting.
         let victim_index = self.pick_index(self.red_zone());
         let victim_node = std::mem::replace(&mut self.entries[victim_index as usize], node.clone());
-        tracing::debug!("evicting red node {:?} from {}", victim_node, victim_index);
+        tracing::trace!("evicting red node {:?} from {}", victim_node, victim_index);
         victim_node.lru_index().clear();
         self.promote_red_to_green(node, victim_index);
         Some(victim_node)
@@ -241,7 +241,7 @@ where
         // going to invoke `self.promote_yellow` next, and it will get
         // updated then.
         let yellow_index = self.pick_index(self.yellow_zone());
-        tracing::debug!(
+        tracing::trace!(
             "demoting yellow node {:?} from {} to red at {}",
             self.entries[yellow_index as usize],
             yellow_index,
@@ -265,7 +265,7 @@ where
 
         // Pick a yellow at random and switch places with it.
         let green_index = self.pick_index(self.green_zone());
-        tracing::debug!(
+        tracing::trace!(
             "demoting green node {:?} from {} to yellow at {}",
             self.entries[green_index as usize],
             green_index,
@@ -275,7 +275,7 @@ where
         self.entries[yellow_index as usize].lru_index().store(yellow_index);
         node.lru_index().store(green_index);
 
-        tracing::debug!("promoted {:?} to green index {}", node, green_index);
+        tracing::trace!("promoted {:?} to green index {}", node, green_index);
     }
 
     fn pick_index(&mut self, zone: std::ops::Range<u16>) -> u16 {
diff --git a/src/tools/rust-analyzer/crates/ra-salsa/src/runtime.rs b/src/tools/rust-analyzer/crates/ra-salsa/src/runtime.rs
index 5fe5f4b46d3..cb16ba0044d 100644
--- a/src/tools/rust-analyzer/crates/ra-salsa/src/runtime.rs
+++ b/src/tools/rust-analyzer/crates/ra-salsa/src/runtime.rs
@@ -9,7 +9,7 @@ use parking_lot::{Mutex, RwLock};
 use std::hash::Hash;
 use std::panic::panic_any;
 use std::sync::atomic::{AtomicU32, Ordering};
-use tracing::debug;
+use tracing::trace;
 use triomphe::{Arc, ThinArc};
 
 mod dependency_graph;
@@ -177,7 +177,7 @@ impl Runtime {
     where
         F: FnOnce(Revision) -> Option<Durability>,
     {
-        tracing::debug!("increment_revision()");
+        tracing::trace!("increment_revision()");
 
         if !self.permits_increment() {
             panic!("increment_revision invoked during a query computation");
@@ -196,7 +196,7 @@ impl Runtime {
 
         let new_revision = current_revision.next();
 
-        debug!("increment_revision: incremented to {:?}", new_revision);
+        trace!("increment_revision: incremented to {:?}", new_revision);
 
         if let Some(d) = op(new_revision) {
             for rev in &self.shared_state.revisions[1..=d.index()] {
@@ -267,7 +267,7 @@ impl Runtime {
         database_key_index: DatabaseKeyIndex,
         to_id: RuntimeId,
     ) {
-        debug!("unblock_cycle_and_maybe_throw(database_key={:?})", database_key_index);
+        trace!("unblock_cycle_and_maybe_throw(database_key={:?})", database_key_index);
 
         let mut from_stack = self.local_state.take_query_stack();
         let from_id = self.id();
@@ -305,7 +305,7 @@ impl Runtime {
 
             Cycle::new(Arc::new(v))
         };
-        debug!("cycle {:?}, cycle_query {:#?}", cycle.debug(db), cycle_query,);
+        trace!("cycle {:?}, cycle_query {:#?}", cycle.debug(db), cycle_query,);
 
         // We can remove the cycle participants from the list of dependencies;
         // they are a strongly connected component (SCC) and we only care about
@@ -323,7 +323,7 @@ impl Runtime {
                     CycleRecoveryStrategy::Fallback => false,
                 })
                 .for_each(|aq| {
-                    debug!("marking {:?} for fallback", aq.database_key_index.debug(db));
+                    trace!("marking {:?} for fallback", aq.database_key_index.debug(db));
                     aq.take_inputs_from(&cycle_query);
                     assert!(aq.cycle.is_none());
                     aq.cycle = Some(cycle.clone());
diff --git a/src/tools/rust-analyzer/crates/ra-salsa/src/runtime/local_state.rs b/src/tools/rust-analyzer/crates/ra-salsa/src/runtime/local_state.rs
index 73869671886..4ab4bad0cc5 100644
--- a/src/tools/rust-analyzer/crates/ra-salsa/src/runtime/local_state.rs
+++ b/src/tools/rust-analyzer/crates/ra-salsa/src/runtime/local_state.rs
@@ -1,4 +1,4 @@
-use tracing::debug;
+use tracing::trace;
 use triomphe::ThinArc;
 
 use crate::durability::Durability;
@@ -78,7 +78,7 @@ impl LocalState {
         durability: Durability,
         changed_at: Revision,
     ) {
-        debug!(
+        trace!(
             "report_query_read_and_unwind_if_cycle_resulted(input={:?}, durability={:?}, changed_at={:?})",
             input, durability, changed_at
         );
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
index fa9ff6b56df..d06130ce8c5 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
@@ -76,7 +76,7 @@ vfs.workspace = true
 paths.workspace = true
 
 [target.'cfg(windows)'.dependencies]
-windows-sys = { version = "0.52", features = ["Win32_System_Threading"] }
+windows-sys = { version = "0.52", features = ["Win32_System_Diagnostics_Debug", "Win32_System_Threading"] }
 
 [target.'cfg(not(target_env = "msvc"))'.dependencies]
 jemallocator = { version = "0.5.0", package = "tikv-jemallocator", optional = true }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/build.rs b/src/tools/rust-analyzer/crates/rust-analyzer/build.rs
index 72b741de00e..0fd381d6122 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/build.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/build.rs
@@ -32,6 +32,7 @@ fn set_rerun() {
 }
 
 fn set_commit_info() {
+    #[allow(clippy::disallowed_methods)]
     let output = match Command::new("git")
         .arg("log")
         .arg("-1")
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 a753621eca8..1a9cdef256d 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
@@ -44,11 +44,7 @@ fn actual_main() -> anyhow::Result<ExitCode> {
 
     #[cfg(debug_assertions)]
     if flags.wait_dbg || env::var("RA_WAIT_DBG").is_ok() {
-        #[allow(unused_mut)]
-        let mut d = 4;
-        while d == 4 {
-            d = 4;
-        }
+        wait_for_debugger();
     }
 
     if let Err(e) = setup_logging(flags.log_file.clone()) {
@@ -96,6 +92,28 @@ fn actual_main() -> anyhow::Result<ExitCode> {
     Ok(ExitCode::SUCCESS)
 }
 
+#[cfg(debug_assertions)]
+fn wait_for_debugger() {
+    #[cfg(target_os = "windows")]
+    {
+        use windows_sys::Win32::System::Diagnostics::Debug::IsDebuggerPresent;
+        // SAFETY: WinAPI generated code that is defensively marked `unsafe` but
+        // in practice can not be used in an unsafe way.
+        while unsafe { IsDebuggerPresent() } == 0 {
+            std::thread::sleep(std::time::Duration::from_millis(100));
+        }
+    }
+    #[cfg(not(target_os = "windows"))]
+    {
+        #[allow(unused_mut)]
+        let mut d = 4;
+        while d == 4 {
+            d = 4;
+            std::thread::sleep(std::time::Duration::from_millis(100));
+        }
+    }
+}
+
 fn setup_logging(log_file_flag: Option<PathBuf>) -> anyhow::Result<()> {
     if cfg!(windows) {
         // This is required so that windows finds our pdb that is placed right beside the exe.
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/rustc_wrapper.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/rustc_wrapper.rs
index 684b3f52afc..b9fcd2e1870 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/rustc_wrapper.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/bin/rustc_wrapper.rs
@@ -46,6 +46,7 @@ fn run_rustc_skipping_cargo_checking(
 }
 
 fn run_rustc(rustc_executable: OsString, args: Vec<OsString>) -> io::Result<ExitCode> {
+    #[allow(clippy::disallowed_methods)]
     let mut child = Command::new(rustc_executable)
         .args(args)
         .stdin(Stdio::inherit())
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 66cd2e424e3..afe3455b780 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
@@ -66,10 +66,6 @@ impl flags::AnalysisStats {
                 true => None,
                 false => Some(RustLibSource::Discover),
             },
-            sysroot_query_metadata: match self.no_query_sysroot_metadata {
-                true => project_model::SysrootQueryMetadata::None,
-                false => project_model::SysrootQueryMetadata::CargoMetadata,
-            },
             all_targets: true,
             set_test: !self.no_test,
             cfg_overrides: CfgOverrides {
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 920a2a37efb..ff24602144a 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
@@ -71,9 +71,6 @@ xflags::xflags! {
             optional --with-deps
             /// Don't load sysroot crates (`std`, `core` & friends).
             optional --no-sysroot
-            /// Don't run cargo metadata on the sysroot to analyze its third-party dependencies.
-            /// Requires --no-sysroot to not be set.
-            optional --no-query-sysroot-metadata
             /// Don't set #[cfg(test)].
             optional --no-test
 
@@ -238,7 +235,6 @@ pub struct AnalysisStats {
     pub only: Option<String>,
     pub with_deps: bool,
     pub no_sysroot: bool,
-    pub no_query_sysroot_metadata: bool,
     pub no_test: bool,
     pub disable_build_scripts: bool,
     pub disable_proc_macros: bool,
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 33c4f31fbee..eb5c44418b7 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
@@ -4,8 +4,9 @@ use std::env;
 use std::time::Instant;
 
 use ide::{
-    Analysis, AnalysisHost, FileId, FileRange, MonikerKind, PackageInformation, RootDatabase,
-    StaticIndex, StaticIndexedFile, TokenId, TokenStaticData, VendoredLibrariesConfig,
+    Analysis, AnalysisHost, FileId, FileRange, MonikerKind, MonikerResult, PackageInformation,
+    RootDatabase, StaticIndex, StaticIndexedFile, TokenId, TokenStaticData,
+    VendoredLibrariesConfig,
 };
 use ide_db::{line_index::WideEncoding, LineIndexDatabase};
 use load_cargo::{load_workspace, LoadCargoConfig, ProcMacroServerChoice};
@@ -167,7 +168,7 @@ impl LsifManager<'_, '_> {
                 out_v: result_set_id.into(),
             }));
         }
-        if let Some(moniker) = token.moniker {
+        if let Some(MonikerResult::Moniker(moniker)) = token.moniker {
             let package_id = self.get_package_id(moniker.package_information);
             let moniker_id = self.add_vertex(lsif::Vertex::Moniker(lsp_types::Moniker {
                 scheme: "rust-analyzer".to_owned(),
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 6483afc85b2..6b0ce4db7c9 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
@@ -10,10 +10,10 @@ use ide::{AnalysisHost, DiagnosticCode, DiagnosticsConfig};
 use itertools::Either;
 use paths::Utf8PathBuf;
 use profile::StopWatch;
-use project_model::target_data_layout::RustcDataLayoutConfig;
+use project_model::toolchain_info::{target_data_layout, QueryConfig};
 use project_model::{
-    target_data_layout, CargoConfig, ManifestPath, ProjectWorkspace, ProjectWorkspaceKind,
-    RustLibSource, Sysroot, SysrootQueryMetadata,
+    CargoConfig, ManifestPath, ProjectWorkspace, ProjectWorkspaceKind, RustLibSource, Sysroot,
+    SysrootSourceWorkspaceConfig,
 };
 
 use load_cargo::{load_workspace, LoadCargoConfig, ProcMacroServerChoice};
@@ -74,13 +74,10 @@ impl Tester {
             ..Default::default()
         };
 
-        let sysroot = Sysroot::discover(
-            tmp_file.parent().unwrap(),
-            &cargo_config.extra_env,
-            SysrootQueryMetadata::CargoMetadata,
-        );
+        let mut sysroot = Sysroot::discover(tmp_file.parent().unwrap(), &cargo_config.extra_env);
+        sysroot.load_workspace(&SysrootSourceWorkspaceConfig::default_cargo());
         let data_layout = target_data_layout::get(
-            RustcDataLayoutConfig::Rustc(&sysroot),
+            QueryConfig::Rustc(&sysroot, tmp_file.parent().unwrap().as_ref()),
             None,
             &cargo_config.extra_env,
         );
@@ -89,7 +86,6 @@ impl Tester {
             kind: ProjectWorkspaceKind::DetachedFile {
                 file: ManifestPath::try_from(tmp_file).unwrap(),
                 cargo: None,
-                cargo_config_extra_env: Default::default(),
                 set_test: true,
             },
             sysroot,
@@ -302,7 +298,7 @@ impl flags::RustcTests {
                     continue;
                 }
             }
-            if p.extension().map_or(true, |x| x != "rs") {
+            if p.extension().is_none_or(|x| x != "rs") {
                 continue;
             }
             if let Err(e) = std::panic::catch_unwind({
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 ff009e69547..6ca7d9ac057 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
@@ -3,14 +3,16 @@
 use std::{path::PathBuf, time::Instant};
 
 use ide::{
-    AnalysisHost, LineCol, MonikerDescriptorKind, MonikerResult, StaticIndex, StaticIndexedFile,
-    SymbolInformationKind, TextRange, TokenId, VendoredLibrariesConfig,
+    AnalysisHost, LineCol, Moniker, MonikerDescriptorKind, MonikerIdentifier, MonikerResult,
+    RootDatabase, StaticIndex, StaticIndexedFile, SymbolInformationKind, TextRange, TokenId,
+    TokenStaticData, VendoredLibrariesConfig,
 };
 use ide_db::LineIndexDatabase;
 use load_cargo::{load_workspace_at, LoadCargoConfig, ProcMacroServerChoice};
 use rustc_hash::{FxHashMap, FxHashSet};
-use scip::types as scip_types;
+use scip::types::{self as scip_types, SymbolInformation};
 use tracing::error;
+use vfs::FileId;
 
 use crate::{
     cli::flags,
@@ -83,32 +85,56 @@ impl flags::Scip {
             text_document_encoding: scip_types::TextEncoding::UTF8.into(),
             special_fields: Default::default(),
         };
-        let mut documents = Vec::new();
-
-        let mut symbols_emitted: FxHashSet<TokenId> = FxHashSet::default();
-        let mut tokens_to_symbol: FxHashMap<TokenId, String> = FxHashMap::default();
-        let mut tokens_to_enclosing_symbol: FxHashMap<TokenId, Option<String>> =
-            FxHashMap::default();
 
-        for StaticIndexedFile { file_id, tokens, .. } in si.files {
-            let mut local_count = 0;
-            let mut new_local_symbol = || {
-                let new_symbol = scip::types::Symbol::new_local(local_count);
-                local_count += 1;
+        let mut documents = Vec::new();
 
-                new_symbol
+        // All TokenIds where an Occurrence has been emitted that references a symbol.
+        let mut token_ids_referenced: FxHashSet<TokenId> = FxHashSet::default();
+        // All TokenIds where the SymbolInformation has been written to the document.
+        let mut token_ids_emitted: FxHashSet<TokenId> = FxHashSet::default();
+        // All FileIds emitted as documents.
+        let mut file_ids_emitted: FxHashSet<FileId> = FxHashSet::default();
+
+        // All non-local symbols encountered, for detecting duplicate symbol errors.
+        let mut nonlocal_symbols_emitted: FxHashSet<String> = FxHashSet::default();
+        // List of (source_location, symbol) for duplicate symbol errors to report.
+        let mut duplicate_symbol_errors: Vec<(String, String)> = Vec::new();
+        // This is called after definitions have been deduplicated by token_ids_emitted. The purpose
+        // is to detect reuse of symbol names because this causes ambiguity about their meaning.
+        let mut record_error_if_symbol_already_used =
+            |symbol: String,
+             is_inherent_impl: bool,
+             relative_path: &str,
+             line_index: &LineIndex,
+             text_range: TextRange| {
+                let is_local = symbol.starts_with("local ");
+                if !is_local && !nonlocal_symbols_emitted.insert(symbol.clone()) {
+                    if is_inherent_impl {
+                        // FIXME: See #18772. Duplicate SymbolInformation for inherent impls is
+                        // omitted. It would be preferable to emit them with numbers with
+                        // disambiguation, but this is more complex to implement.
+                        false
+                    } else {
+                        let source_location =
+                            text_range_to_string(relative_path, line_index, text_range);
+                        duplicate_symbol_errors.push((source_location, symbol));
+                        // Keep duplicate SymbolInformation. This behavior is preferred over
+                        // omitting so that the issue might be visible within downstream tools.
+                        true
+                    }
+                } else {
+                    true
+                }
             };
 
-            let relative_path = match get_relative_filepath(&vfs, &root, file_id) {
-                Some(relative_path) => relative_path,
-                None => continue,
-            };
+        // Generates symbols from token monikers.
+        let mut symbol_generator = SymbolGenerator::new();
 
-            let line_index = LineIndex {
-                index: db.line_index(file_id),
-                encoding: PositionEncoding::Utf8,
-                endings: LineEndings::Unix,
-            };
+        for StaticIndexedFile { file_id, tokens, .. } in si.files {
+            symbol_generator.clear_document_local_state();
+
+            let Some(relative_path) = get_relative_filepath(&vfs, &root, file_id) else { continue };
+            let line_index = get_line_index(db, file_id);
 
             let mut occurrences = Vec::new();
             let mut symbols = Vec::new();
@@ -116,71 +142,58 @@ impl flags::Scip {
             tokens.into_iter().for_each(|(text_range, id)| {
                 let token = si.tokens.get(id).unwrap();
 
-                let range = text_range_to_scip_range(&line_index, text_range);
-                let symbol = tokens_to_symbol
-                    .entry(id)
-                    .or_insert_with(|| {
-                        let symbol = token
-                            .moniker
-                            .as_ref()
-                            .map(moniker_to_symbol)
-                            .unwrap_or_else(&mut new_local_symbol);
-                        scip::symbol::format_symbol(symbol)
-                    })
-                    .clone();
-                let enclosing_symbol = tokens_to_enclosing_symbol
-                    .entry(id)
-                    .or_insert_with(|| {
-                        token
-                            .enclosing_moniker
-                            .as_ref()
-                            .map(moniker_to_symbol)
-                            .map(scip::symbol::format_symbol)
-                    })
-                    .clone();
-
-                let mut symbol_roles = Default::default();
-
-                if let Some(def) = token.definition {
-                    // if the range of the def and the range of the token are the same, this must be the definition.
-                    // they also must be in the same file. See https://github.com/rust-lang/rust-analyzer/pull/17988
-                    if def.file_id == file_id && def.range == text_range {
-                        symbol_roles |= scip_types::SymbolRole::Definition as i32;
+                let (symbol, enclosing_symbol, is_inherent_impl) =
+                    if let Some(TokenSymbols { symbol, enclosing_symbol, is_inherent_impl }) =
+                        symbol_generator.token_symbols(id, token)
+                    {
+                        (symbol, enclosing_symbol, is_inherent_impl)
+                    } else {
+                        ("".to_owned(), None, false)
+                    };
+
+                if !symbol.is_empty() {
+                    let is_defined_in_this_document = match token.definition {
+                        Some(def) => def.file_id == file_id,
+                        _ => false,
+                    };
+                    if is_defined_in_this_document {
+                        if token_ids_emitted.insert(id) {
+                            // token_ids_emitted does deduplication. This checks that this results
+                            // in unique emitted symbols, as otherwise references are ambiguous.
+                            let should_emit = record_error_if_symbol_already_used(
+                                symbol.clone(),
+                                is_inherent_impl,
+                                relative_path.as_str(),
+                                &line_index,
+                                text_range,
+                            );
+                            if should_emit {
+                                symbols.push(compute_symbol_info(
+                                    symbol.clone(),
+                                    enclosing_symbol,
+                                    token,
+                                ));
+                            }
+                        }
+                    } else {
+                        token_ids_referenced.insert(id);
                     }
+                }
 
-                    if symbols_emitted.insert(id) {
-                        let documentation = match &token.documentation {
-                            Some(doc) => vec![doc.as_str().to_owned()],
-                            None => vec![],
-                        };
-
-                        let position_encoding =
-                            scip_types::PositionEncoding::UTF8CodeUnitOffsetFromLineStart.into();
-                        let signature_documentation =
-                            token.signature.clone().map(|text| scip_types::Document {
-                                relative_path: relative_path.clone(),
-                                language: "rust".to_owned(),
-                                text,
-                                position_encoding,
-                                ..Default::default()
-                            });
-                        let symbol_info = scip_types::SymbolInformation {
-                            symbol: symbol.clone(),
-                            documentation,
-                            relationships: Vec::new(),
-                            special_fields: Default::default(),
-                            kind: symbol_kind(token.kind).into(),
-                            display_name: token.display_name.clone().unwrap_or_default(),
-                            signature_documentation: signature_documentation.into(),
-                            enclosing_symbol: enclosing_symbol.unwrap_or_default(),
-                        };
-
-                        symbols.push(symbol_info)
-                    }
+                // If the range of the def and the range of the token are the same, this must be the definition.
+                // they also must be in the same file. See https://github.com/rust-lang/rust-analyzer/pull/17988
+                let is_definition = match token.definition {
+                    Some(def) => def.file_id == file_id && def.range == text_range,
+                    _ => false,
+                };
+
+                let mut symbol_roles = Default::default();
+                if is_definition {
+                    symbol_roles |= scip_types::SymbolRole::Definition as i32;
                 }
 
                 occurrences.push(scip_types::Occurrence {
-                    range,
+                    range: text_range_to_scip_range(&line_index, text_range),
                     symbol,
                     symbol_roles,
                     override_documentation: Vec::new(),
@@ -206,15 +219,63 @@ impl flags::Scip {
                 position_encoding,
                 special_fields: Default::default(),
             });
+            if !file_ids_emitted.insert(file_id) {
+                panic!("Invariant violation: file emitted multiple times.");
+            }
+        }
+
+        // Collect all symbols referenced by the files but not defined within them.
+        let mut external_symbols = Vec::new();
+        for id in token_ids_referenced.difference(&token_ids_emitted) {
+            let id = *id;
+            let token = si.tokens.get(id).unwrap();
+
+            let Some(definition) = token.definition else {
+                break;
+            };
+
+            let file_id = definition.file_id;
+            let Some(relative_path) = get_relative_filepath(&vfs, &root, file_id) else { continue };
+            let line_index = get_line_index(db, file_id);
+            let text_range = definition.range;
+            if file_ids_emitted.contains(&file_id) {
+                tracing::error!(
+                    "Bug: definition at {} should have been in an SCIP document but was not.",
+                    text_range_to_string(relative_path.as_str(), &line_index, text_range)
+                );
+                continue;
+            }
+
+            let TokenSymbols { symbol, enclosing_symbol, .. } = symbol_generator
+                .token_symbols(id, token)
+                .expect("To have been referenced, the symbol must be in the cache.");
+
+            record_error_if_symbol_already_used(
+                symbol.clone(),
+                false,
+                relative_path.as_str(),
+                &line_index,
+                text_range,
+            );
+            external_symbols.push(compute_symbol_info(symbol.clone(), enclosing_symbol, token));
         }
 
         let index = scip_types::Index {
             metadata: Some(metadata).into(),
             documents,
-            external_symbols: Vec::new(),
+            external_symbols,
             special_fields: Default::default(),
         };
 
+        if !duplicate_symbol_errors.is_empty() {
+            eprintln!("{}", DUPLICATE_SYMBOLS_MESSAGE);
+            for (source_location, symbol) in duplicate_symbol_errors {
+                eprintln!("{}", source_location);
+                eprintln!("  Duplicate symbol: {}", symbol);
+                eprintln!();
+            }
+        }
+
         let out_path = self.output.unwrap_or_else(|| PathBuf::from(r"index.scip"));
         scip::write_message_to_file(out_path, index)
             .map_err(|err| anyhow::format_err!("Failed to write scip to file: {}", err))?;
@@ -224,6 +285,53 @@ impl flags::Scip {
     }
 }
 
+// FIXME: Known buggy cases are described here.
+const DUPLICATE_SYMBOLS_MESSAGE: &str = "
+Encountered duplicate scip symbols, indicating an internal rust-analyzer bug. These duplicates are
+included in the output, but this causes information lookup to be ambiguous and so information about
+these symbols presented by downstream tools may be incorrect.
+
+Known rust-analyzer bugs that can cause this:
+
+  * Definitions in crate example binaries which have the same symbol as definitions in the library
+    or some other example.
+
+  * Struct/enum/const/static/impl definitions nested in a function do not mention the function name.
+    See #18771.
+
+Duplicate symbols encountered:
+";
+
+fn compute_symbol_info(
+    symbol: String,
+    enclosing_symbol: Option<String>,
+    token: &TokenStaticData,
+) -> SymbolInformation {
+    let documentation = match &token.documentation {
+        Some(doc) => vec![doc.as_str().to_owned()],
+        None => vec![],
+    };
+
+    let position_encoding = scip_types::PositionEncoding::UTF8CodeUnitOffsetFromLineStart.into();
+    let signature_documentation = token.signature.clone().map(|text| scip_types::Document {
+        relative_path: "".to_owned(),
+        language: "rust".to_owned(),
+        text,
+        position_encoding,
+        ..Default::default()
+    });
+    scip_types::SymbolInformation {
+        symbol,
+        documentation,
+        relationships: Vec::new(),
+        special_fields: Default::default(),
+        kind: symbol_kind(token.kind).into(),
+        display_name: token.display_name.clone().unwrap_or_default(),
+        signature_documentation: signature_documentation.into(),
+        enclosing_symbol: enclosing_symbol.unwrap_or_default(),
+    }
+}
+
 fn get_relative_filepath(
     vfs: &vfs::Vfs,
     rootpath: &vfs::AbsPathBuf,
@@ -232,6 +340,14 @@ fn get_relative_filepath(
     Some(vfs.file_path(file_id).as_path()?.strip_prefix(rootpath)?.as_str().to_owned())
 }
 
+fn get_line_index(db: &RootDatabase, file_id: FileId) -> LineIndex {
+    LineIndex {
+        index: db.line_index(file_id),
+        encoding: PositionEncoding::Utf8,
+        endings: LineEndings::Unix,
+    }
+}
+
 // SCIP Ranges have a (very large) optimization that ranges if they are on the same line
 // only encode as a vector of [start_line, start_col, end_col].
 //
@@ -247,6 +363,13 @@ fn text_range_to_scip_range(line_index: &LineIndex, range: TextRange) -> Vec<i32
     }
 }
 
+fn text_range_to_string(relative_path: &str, line_index: &LineIndex, range: TextRange) -> String {
+    let LineCol { line: start_line, col: start_col } = line_index.index.line_col(range.start());
+    let LineCol { line: end_line, col: end_col } = line_index.index.line_col(range.end());
+
+    format!("{relative_path}:{start_line}:{start_col}-{end_line}:{end_col}")
+}
+
 fn new_descriptor_str(
     name: &str,
     suffix: scip_types::descriptor::Suffix,
@@ -259,14 +382,6 @@ fn new_descriptor_str(
     }
 }
 
-fn new_descriptor(name: &str, suffix: scip_types::descriptor::Suffix) -> scip_types::Descriptor {
-    if name.contains('\'') {
-        new_descriptor_str(&format!("`{name}`"), suffix)
-    } else {
-        new_descriptor_str(name, suffix)
-    }
-}
-
 fn symbol_kind(kind: SymbolInformationKind) -> scip_types::symbol_information::Kind {
     use scip_types::symbol_information::Kind as ScipKind;
     match kind {
@@ -295,17 +410,91 @@ fn symbol_kind(kind: SymbolInformationKind) -> scip_types::symbol_information::K
     }
 }
 
-fn moniker_to_symbol(moniker: &MonikerResult) -> scip_types::Symbol {
-    use scip_types::descriptor::Suffix::*;
+#[derive(Clone)]
+struct TokenSymbols {
+    symbol: String,
+    /// Definition that contains this one. Only set when `symbol` is local.
+    enclosing_symbol: Option<String>,
+    /// True if this symbol is for an inherent impl. This is used to only emit `SymbolInformation`
+    /// for a struct's first inherent impl, since their symbol names are not disambiguated.
+    is_inherent_impl: bool,
+}
+
+struct SymbolGenerator {
+    token_to_symbols: FxHashMap<TokenId, Option<TokenSymbols>>,
+    local_count: usize,
+}
+
+impl SymbolGenerator {
+    fn new() -> Self {
+        SymbolGenerator { token_to_symbols: FxHashMap::default(), local_count: 0 }
+    }
+
+    fn clear_document_local_state(&mut self) {
+        self.local_count = 0;
+    }
+
+    fn token_symbols(&mut self, id: TokenId, token: &TokenStaticData) -> Option<TokenSymbols> {
+        let mut local_count = self.local_count;
+        let token_symbols = self
+            .token_to_symbols
+            .entry(id)
+            .or_insert_with(|| {
+                Some(match token.moniker.as_ref()? {
+                    MonikerResult::Moniker(moniker) => TokenSymbols {
+                        symbol: scip::symbol::format_symbol(moniker_to_symbol(moniker)),
+                        enclosing_symbol: None,
+                        is_inherent_impl: moniker
+                            .identifier
+                            .description
+                            .get(moniker.identifier.description.len() - 2)
+                            .is_some_and(|descriptor| {
+                                descriptor.desc == MonikerDescriptorKind::Type
+                                    && descriptor.name == "impl"
+                            }),
+                    },
+                    MonikerResult::Local { enclosing_moniker } => {
+                        let local_symbol = scip::types::Symbol::new_local(local_count);
+                        local_count += 1;
+                        TokenSymbols {
+                            symbol: scip::symbol::format_symbol(local_symbol),
+                            enclosing_symbol: enclosing_moniker
+                                .as_ref()
+                                .map(moniker_to_symbol)
+                                .map(scip::symbol::format_symbol),
+                            is_inherent_impl: false,
+                        }
+                    }
+                })
+            })
+            .clone();
+        self.local_count = local_count;
+        token_symbols
+    }
+}
+
+fn moniker_to_symbol(moniker: &Moniker) -> scip_types::Symbol {
+    scip_types::Symbol {
+        scheme: "rust-analyzer".into(),
+        package: Some(scip_types::Package {
+            manager: "cargo".to_owned(),
+            name: moniker.package_information.name.clone(),
+            version: moniker.package_information.version.clone().unwrap_or_else(|| ".".to_owned()),
+            special_fields: Default::default(),
+        })
+        .into(),
+        descriptors: moniker_descriptors(&moniker.identifier),
+        special_fields: Default::default(),
+    }
+}
 
-    let package_name = moniker.package_information.name.clone();
-    let version = moniker.package_information.version.clone();
-    let descriptors = moniker
-        .identifier
+fn moniker_descriptors(identifier: &MonikerIdentifier) -> Vec<scip_types::Descriptor> {
+    use scip_types::descriptor::Suffix::*;
+    identifier
         .description
         .iter()
         .map(|desc| {
-            new_descriptor(
+            new_descriptor_str(
                 &desc.name,
                 match desc.desc {
                     MonikerDescriptorKind::Namespace => Namespace,
@@ -319,27 +508,13 @@ fn moniker_to_symbol(moniker: &MonikerResult) -> scip_types::Symbol {
                 },
             )
         })
-        .collect();
-
-    scip_types::Symbol {
-        scheme: "rust-analyzer".into(),
-        package: Some(scip_types::Package {
-            manager: "cargo".to_owned(),
-            name: package_name,
-            version: version.unwrap_or_else(|| ".".to_owned()),
-            special_fields: Default::default(),
-        })
-        .into(),
-        descriptors,
-        special_fields: Default::default(),
-    }
+        .collect()
 }
 
 #[cfg(test)]
 mod test {
     use super::*;
     use ide::{FilePosition, TextSize};
-    use scip::symbol::format_symbol;
     use test_fixture::ChangeFixture;
     use vfs::VfsPath;
 
@@ -376,7 +551,21 @@ mod test {
             for &(range, id) in &file.tokens {
                 if range.contains(offset - TextSize::from(1)) {
                     let token = si.tokens.get(id).unwrap();
-                    found_symbol = token.moniker.as_ref().map(moniker_to_symbol);
+                    found_symbol = match token.moniker.as_ref() {
+                        None => None,
+                        Some(MonikerResult::Moniker(moniker)) => {
+                            Some(scip::symbol::format_symbol(moniker_to_symbol(moniker)))
+                        }
+                        Some(MonikerResult::Local { enclosing_moniker: Some(moniker) }) => {
+                            Some(format!(
+                                "local enclosed by {}",
+                                scip::symbol::format_symbol(moniker_to_symbol(moniker))
+                            ))
+                        }
+                        Some(MonikerResult::Local { enclosing_moniker: None }) => {
+                            Some("unenclosed local".to_owned())
+                        }
+                    };
                     break;
                 }
             }
@@ -388,9 +577,7 @@ mod test {
         }
 
         assert!(found_symbol.is_some(), "must have one symbol {found_symbol:?}");
-        let res = found_symbol.unwrap();
-        let formatted = format_symbol(res);
-        assert_eq!(formatted, expected);
+        assert_eq!(found_symbol.unwrap(), expected);
     }
 
     #[test]
@@ -467,8 +654,7 @@ pub mod module {
         }
     }
     "#,
-            // "foo::module::MyTrait::MyType",
-            "rust-analyzer cargo foo 0.1.0 module/MyTrait#[MyType]",
+            "rust-analyzer cargo foo 0.1.0 module/MyTrait#MyType#",
         );
     }
 
@@ -489,8 +675,7 @@ pub mod module {
         }
     }
     "#,
-            // "foo::module::MyStruct::MyTrait::func",
-            "rust-analyzer cargo foo 0.1.0 module/MyStruct#MyTrait#func().",
+            "rust-analyzer cargo foo 0.1.0 module/impl#[MyStruct][MyTrait]func().",
         );
     }
 
@@ -526,7 +711,7 @@ pub mod example_mod {
     pub fn func(x$0: usize) {}
 }
 "#,
-            "rust-analyzer cargo foo 0.1.0 example_mod/func().(x)",
+            "local enclosed by rust-analyzer cargo foo 0.1.0 example_mod/func().",
         );
     }
 
@@ -546,7 +731,7 @@ pub mod example_mod {
     }
 }
 "#,
-            "rust-analyzer cargo foo 0.1.0 example_mod/func().(x)",
+            "local enclosed by rust-analyzer cargo foo 0.1.0 example_mod/func().",
         );
     }
 
@@ -566,7 +751,7 @@ pub mod example_mod {
         }
     }
     "#,
-            "",
+            "local enclosed by rust-analyzer cargo foo 0.1.0 module/func().",
         );
     }
 
@@ -609,7 +794,7 @@ pub mod example_mod {
     }
 
     #[test]
-    fn symbol_for_for_type_alias() {
+    fn symbol_for_type_alias() {
         check_symbol(
             r#"
     //- /workspace/lib.rs crate:main
@@ -619,6 +804,70 @@ pub mod example_mod {
         );
     }
 
+    // FIXME: This test represents current misbehavior.
+    #[test]
+    fn symbol_for_nested_function() {
+        check_symbol(
+            r#"
+    //- /workspace/lib.rs crate:main
+    pub fn func() {
+       pub fn inner_func$0() {}
+    }
+    "#,
+            "rust-analyzer cargo main . inner_func().",
+            // FIXME: This should be a local:
+            // "local enclosed by rust-analyzer cargo main . func().",
+        );
+    }
+
+    // FIXME: This test represents current misbehavior.
+    #[test]
+    fn symbol_for_struct_in_function() {
+        check_symbol(
+            r#"
+    //- /workspace/lib.rs crate:main
+    pub fn func() {
+       struct SomeStruct$0 {}
+    }
+    "#,
+            "rust-analyzer cargo main . SomeStruct#",
+            // FIXME: This should be a local:
+            // "local enclosed by rust-analyzer cargo main . func().",
+        );
+    }
+
+    // FIXME: This test represents current misbehavior.
+    #[test]
+    fn symbol_for_const_in_function() {
+        check_symbol(
+            r#"
+    //- /workspace/lib.rs crate:main
+    pub fn func() {
+       const SOME_CONST$0: u32 = 1;
+    }
+    "#,
+            "rust-analyzer cargo main . SOME_CONST.",
+            // FIXME: This should be a local:
+            // "local enclosed by rust-analyzer cargo main . func().",
+        );
+    }
+
+    // FIXME: This test represents current misbehavior.
+    #[test]
+    fn symbol_for_static_in_function() {
+        check_symbol(
+            r#"
+    //- /workspace/lib.rs crate:main
+    pub fn func() {
+       static SOME_STATIC$0: u32 = 1;
+    }
+    "#,
+            "rust-analyzer cargo main . SOME_STATIC.",
+            // FIXME: This should be a local:
+            // "local enclosed by rust-analyzer cargo main . func().",
+        );
+    }
+
     #[test]
     fn documentation_matches_doc_comment() {
         let s = "/// foo\nfn bar() {}";
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 b06117f7383..30f0031905f 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -50,6 +50,14 @@ mod patch_old_style;
 //  - Don't use abbreviations unless really necessary
 //  - foo_command = overrides the subcommand, foo_overrideCommand allows full overwriting, extra args only applies for foo_command
 
+#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub enum MaxSubstitutionLength {
+    Hide,
+    #[serde(untagged)]
+    Limit(usize),
+}
+
 // Defines the server-side configuration of the rust-analyzer. We generate
 // *parts* of VS Code's `package.json` config from this. Run `cargo test` to
 // re-generate that file.
@@ -111,6 +119,9 @@ config_data! {
         /// Whether to show `Run` action. Only applies when
         /// `#rust-analyzer.hover.actions.enable#` is set.
         hover_actions_run_enable: bool             = true,
+        /// Whether to show `Update Test` action. Only applies when
+        /// `#rust-analyzer.hover.actions.enable#` and `#rust-analyzer.hover.actions.run.enable#` are set.
+        hover_actions_updateTest_enable: bool     = true,
 
         /// Whether to show documentation on hover.
         hover_documentation_enable: bool           = true,
@@ -119,6 +130,12 @@ config_data! {
         hover_documentation_keywords_enable: bool  = true,
         /// Use markdown syntax for links on hover.
         hover_links_enable: bool = true,
+        /// Whether to show what types are used as generic arguments in calls etc. on hover, and what is their max length to show such types, beyond it they will be shown with ellipsis.
+        ///
+        /// This can take three values: `null` means "unlimited", the string `"hide"` means to not show generic substitutions at all, and a number means to limit them to X characters.
+        ///
+        /// The default is 20 characters.
+        hover_maxSubstitutionLength: Option<MaxSubstitutionLength> = Some(MaxSubstitutionLength::Limit(20)),
         /// How to render the align information in a memory layout hover.
         hover_memoryLayout_alignment: Option<MemoryLayoutHoverRenderKindDef> = Some(MemoryLayoutHoverRenderKindDef::Hexadecimal),
         /// Whether to show memory layout data on hover.
@@ -229,6 +246,9 @@ config_data! {
         /// Whether to show `Run` lens. Only applies when
         /// `#rust-analyzer.lens.enable#` is set.
         lens_run_enable: bool              = true,
+        /// Whether to show `Update Test` lens. Only applies when
+        /// `#rust-analyzer.lens.enable#` and `#rust-analyzer.lens.run.enable#` are set.
+        lens_updateTest_enable: bool = true,
 
         /// Disable project auto-discovery in favor of explicitly specified set
         /// of projects.
@@ -426,11 +446,32 @@ config_data! {
         /// Toggles the additional completions that automatically add imports when completed.
         /// Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
         completion_autoimport_enable: bool       = true,
+        /// A list of full paths to items to exclude from auto-importing completions.
+        ///
+        /// Traits in this list won't have their methods suggested in completions unless the trait
+        /// is in scope.
+        ///
+        /// You can either specify a string path which defaults to type "always" or use the more verbose
+        /// form `{ "path": "path::to::item", type: "always" }`.
+        ///
+        /// For traits the type "methods" can be used to only exclude the methods but not the trait itself.
+        ///
+        /// This setting also inherits `#rust-analyzer.completion.excludeTraits#`.
+        completion_autoimport_exclude: Vec<AutoImportExclusion> = vec![
+            AutoImportExclusion::Verbose { path: "core::borrow::Borrow".to_owned(), r#type: AutoImportExclusionType::Methods },
+            AutoImportExclusion::Verbose { path: "core::borrow::BorrowMut".to_owned(), r#type: AutoImportExclusionType::Methods },
+        ],
         /// Toggles the additional completions that automatically show method calls and field accesses
         /// with `self` prefixed to them when inside a method.
         completion_autoself_enable: bool        = true,
         /// Whether to add parenthesis and argument snippets when completing function.
         completion_callable_snippets: CallableCompletionDef  = CallableCompletionDef::FillArguments,
+        /// A list of full paths to traits whose methods to exclude from completion.
+        ///
+        /// Methods from these traits won't be completed, even if the trait is in scope. However, they will still be suggested on expressions whose type is `dyn Trait`, `impl Trait` or `T where T: Trait`.
+        ///
+        /// Note that the trait themselves can still be completed.
+        completion_excludeTraits: Vec<String> = Vec::new(),
         /// Whether to show full function/method signatures in completion docs.
         completion_fullFunctionSignatures_enable: bool = false,
         /// Whether to omit deprecated items from autocompletion. By default they are marked as deprecated but not hidden.
@@ -554,15 +595,12 @@ config_data! {
         ///
         /// This option does not take effect until rust-analyzer is restarted.
         cargo_sysroot: Option<String>    = Some("discover".to_owned()),
-        /// How to query metadata for the sysroot crate. Using cargo metadata allows rust-analyzer
-        /// to analyze third-party dependencies of the standard libraries.
-        cargo_sysrootQueryMetadata: SysrootQueryMetadata = SysrootQueryMetadata::CargoMetadata,
         /// Relative path to the sysroot library sources. If left unset, this will default to
         /// `{cargo.sysroot}/lib/rustlib/src/rust/library`.
         ///
         /// This option does not take effect until rust-analyzer is restarted.
         cargo_sysrootSrc: Option<String>    = None,
-        /// Compilation target override (target triple).
+        /// Compilation target override (target tuple).
         // FIXME(@poliorcetics): move to multiple targets here too, but this will need more work
         // than `checkOnSave_target`
         cargo_target: Option<String>     = None,
@@ -854,7 +892,7 @@ impl Config {
         if let Some(mut json) = change.client_config_change {
             tracing::info!("updating config from JSON: {:#}", json);
 
-            if !(json.is_null() || json.as_object().map_or(false, |it| it.is_empty())) {
+            if !(json.is_null() || json.as_object().is_some_and(|it| it.is_empty())) {
                 let mut json_errors = vec![];
                 let detached_files = get_field_json::<Vec<Utf8PathBuf>>(
                     &mut json,
@@ -869,11 +907,18 @@ impl Config {
 
                 patch_old_style::patch_json_for_outdated_configs(&mut json);
 
+                let mut json_errors = vec![];
+                let snips = get_field_json::<FxHashMap<String, SnippetDef>>(
+                    &mut json,
+                    &mut json_errors,
+                    "completion_snippets_custom",
+                    None,
+                )
+                .unwrap_or(self.completion_snippets_custom().to_owned());
+
                 // IMPORTANT : This holds as long as ` completion_snippets_custom` is declared `client`.
                 config.snippets.clear();
 
-                let snips = self.completion_snippets_custom().to_owned();
-
                 for (name, def) in snips.iter() {
                     if def.prefix.is_empty() && def.postfix.is_empty() {
                         continue;
@@ -1147,6 +1192,7 @@ pub struct LensConfig {
     // runnables
     pub run: bool,
     pub debug: bool,
+    pub update_test: bool,
     pub interpret: bool,
 
     // implementations
@@ -1182,6 +1228,7 @@ impl LensConfig {
     pub fn any(&self) -> bool {
         self.run
             || self.debug
+            || self.update_test
             || self.implementations
             || self.method_refs
             || self.refs_adt
@@ -1194,7 +1241,7 @@ impl LensConfig {
     }
 
     pub fn runnable(&self) -> bool {
-        self.run || self.debug
+        self.run || self.debug || self.update_test
     }
 
     pub fn references(&self) -> bool {
@@ -1208,6 +1255,7 @@ pub struct HoverActionsConfig {
     pub references: bool,
     pub run: bool,
     pub debug: bool,
+    pub update_test: bool,
     pub goto_type_def: bool,
 }
 
@@ -1217,6 +1265,7 @@ impl HoverActionsConfig {
         references: false,
         run: false,
         debug: false,
+        update_test: false,
         goto_type_def: false,
     };
 
@@ -1229,7 +1278,7 @@ impl HoverActionsConfig {
     }
 
     pub fn runnable(&self) -> bool {
-        self.run || self.debug
+        self.run || self.debug || self.update_test
     }
 }
 
@@ -1417,7 +1466,7 @@ impl Config {
         CallHierarchyConfig { exclude_tests: self.references_excludeTests().to_owned() }
     }
 
-    pub fn completion(&self, source_root: Option<SourceRootId>) -> CompletionConfig {
+    pub fn completion(&self, source_root: Option<SourceRootId>) -> CompletionConfig<'_> {
         let client_capability_fields = self.completion_resolve_support_properties();
         CompletionConfig {
             enable_postfix_completions: self.completion_postfix_enable(source_root).to_owned(),
@@ -1448,6 +1497,27 @@ impl Config {
             } else {
                 CompletionFieldsToResolve::from_client_capabilities(&client_capability_fields)
             },
+            exclude_flyimport: self
+                .completion_autoimport_exclude(source_root)
+                .iter()
+                .map(|it| match it {
+                    AutoImportExclusion::Path(path) => {
+                        (path.clone(), ide_completion::AutoImportExclusionType::Always)
+                    }
+                    AutoImportExclusion::Verbose { path, r#type } => (
+                        path.clone(),
+                        match r#type {
+                            AutoImportExclusionType::Always => {
+                                ide_completion::AutoImportExclusionType::Always
+                            }
+                            AutoImportExclusionType::Methods => {
+                                ide_completion::AutoImportExclusionType::Methods
+                            }
+                        },
+                    ),
+                })
+                .collect(),
+            exclude_traits: self.completion_excludeTraits(source_root),
         }
     }
 
@@ -1503,6 +1573,9 @@ impl Config {
             references: enable && self.hover_actions_references_enable().to_owned(),
             run: enable && self.hover_actions_run_enable().to_owned(),
             debug: enable && self.hover_actions_debug_enable().to_owned(),
+            update_test: enable
+                && self.hover_actions_run_enable().to_owned()
+                && self.hover_actions_updateTest_enable().to_owned(),
             goto_type_def: enable && self.hover_actions_gotoTypeDef_enable().to_owned(),
         }
     }
@@ -1533,6 +1606,11 @@ impl Config {
             max_trait_assoc_items_count: self.hover_show_traitAssocItems().to_owned(),
             max_fields_count: self.hover_show_fields().to_owned(),
             max_enum_variants_count: self.hover_show_enumVariants().to_owned(),
+            max_subst_ty_len: match self.hover_maxSubstitutionLength() {
+                Some(MaxSubstitutionLength::Hide) => ide::SubstTyLen::Hide,
+                Some(MaxSubstitutionLength::Limit(limit)) => ide::SubstTyLen::LimitTo(*limit),
+                None => ide::SubstTyLen::Unlimited,
+            },
         }
     }
 
@@ -1860,12 +1938,6 @@ impl Config {
             },
             target: self.cargo_target(source_root).clone(),
             sysroot,
-            sysroot_query_metadata: match self.cargo_sysrootQueryMetadata(None) {
-                SysrootQueryMetadata::CargoMetadata => {
-                    project_model::SysrootQueryMetadata::CargoMetadata
-                }
-                SysrootQueryMetadata::None => project_model::SysrootQueryMetadata::None,
-            },
             sysroot_src,
             rustc_source,
             cfg_overrides: project_model::CfgOverrides {
@@ -1969,7 +2041,7 @@ impl Config {
 
     pub(crate) fn cargo_test_options(&self, source_root: Option<SourceRootId>) -> CargoOptions {
         CargoOptions {
-            target_triples: self.cargo_target(source_root).clone().into_iter().collect(),
+            target_tuples: self.cargo_target(source_root).clone().into_iter().collect(),
             all_targets: false,
             no_default_features: *self.cargo_noDefaultFeatures(source_root),
             all_features: matches!(self.cargo_features(source_root), CargoFeaturesDef::All),
@@ -2004,7 +2076,7 @@ impl Config {
             Some(_) | None => FlycheckConfig::CargoCommand {
                 command: self.check_command(source_root).clone(),
                 options: CargoOptions {
-                    target_triples: self
+                    target_tuples: self
                         .check_targets(source_root)
                         .clone()
                         .and_then(|targets| match &targets.0[..] {
@@ -2047,11 +2119,13 @@ impl Config {
     fn target_dir_from_config(&self, source_root: Option<SourceRootId>) -> Option<Utf8PathBuf> {
         self.cargo_targetDir(source_root).as_ref().and_then(|target_dir| match target_dir {
             TargetDirectory::UseSubdirectory(true) => {
-                Some(Utf8PathBuf::from("target/rust-analyzer"))
+                let env_var = env::var("CARGO_TARGET_DIR").ok();
+                let mut path = Utf8PathBuf::from(env_var.as_deref().unwrap_or("target"));
+                path.push("rust-analyzer");
+                Some(path)
             }
             TargetDirectory::UseSubdirectory(false) => None,
-            TargetDirectory::Directory(dir) if dir.is_relative() => Some(dir.clone()),
-            TargetDirectory::Directory(_) => None,
+            TargetDirectory::Directory(dir) => Some(dir.clone()),
         })
     }
 
@@ -2096,6 +2170,9 @@ impl Config {
         LensConfig {
             run: *self.lens_enable() && *self.lens_run_enable(),
             debug: *self.lens_enable() && *self.lens_debug_enable(),
+            update_test: *self.lens_enable()
+                && *self.lens_updateTest_enable()
+                && *self.lens_run_enable(),
             interpret: *self.lens_enable() && *self.lens_run_enable() && *self.interpret_tests(),
             implementations: *self.lens_enable() && *self.lens_implementations_enable(),
             method_refs: *self.lens_enable() && *self.lens_references_method_enable(),
@@ -2378,6 +2455,21 @@ enum ExprFillDefaultDef {
 }
 
 #[derive(Serialize, Deserialize, Debug, Clone)]
+#[serde(untagged)]
+#[serde(rename_all = "snake_case")]
+pub enum AutoImportExclusion {
+    Path(String),
+    Verbose { path: String, r#type: AutoImportExclusionType },
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+#[serde(rename_all = "snake_case")]
+pub enum AutoImportExclusionType {
+    Always,
+    Methods,
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
 #[serde(rename_all = "snake_case")]
 enum ImportGranularityDef {
     Preserve,
@@ -2568,13 +2660,6 @@ pub enum NumThreads {
     Concrete(usize),
 }
 
-#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
-#[serde(rename_all = "snake_case")]
-pub enum SysrootQueryMetadata {
-    CargoMetadata,
-    None,
-}
-
 macro_rules! _default_val {
     (@verbatim: $s:literal, $ty:ty) => {{
         let default_: $ty = serde_json::from_str(&$s).unwrap();
@@ -3426,13 +3511,45 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
                 }
             ]
         },
-        "SysrootQueryMetadata" => set! {
-            "type": "string",
-            "enum": ["none", "cargo_metadata"],
-            "enumDescriptions": [
-                "Do not query sysroot metadata, always use stitched sysroot.",
-                "Use `cargo metadata` to query sysroot metadata."
-            ],
+        "Option<MaxSubstitutionLength>" => set! {
+            "anyOf": [
+                {
+                    "type": "null"
+                },
+                {
+                    "type": "string",
+                    "enum": ["hide"]
+                },
+                {
+                    "type": "integer"
+                }
+            ]
+        },
+        "Vec<AutoImportExclusion>" => set! {
+            "type": "array",
+            "items": {
+                "anyOf": [
+                    {
+                        "type": "string",
+                    },
+                    {
+                        "type": "object",
+                        "properties": {
+                            "path": {
+                                "type": "string",
+                            },
+                            "type": {
+                                "type": "string",
+                                "enum": ["always", "methods"],
+                                "enumDescriptions": [
+                                    "Do not show this item or its methods (if it is a trait) in auto-import completions.",
+                                    "Do not show this traits methods in auto-import completions."
+                                ],
+                            },
+                        }
+                    }
+                ]
+             }
         },
         _ => panic!("missing entry for {ty}: {default} (field {field})"),
     }
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 c3ab7f3ae71..fafffa043f9 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
@@ -500,7 +500,7 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
 fn rustc_code_description(code: Option<&str>) -> Option<lsp_types::CodeDescription> {
     code.filter(|code| {
         let mut chars = code.chars();
-        chars.next().map_or(false, |c| c == 'E')
+        chars.next() == Some('E')
             && chars.by_ref().take(4).all(|c| c.is_ascii_digit())
             && chars.next().is_none()
     })
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs
index 96b164228ef..0c111319bb4 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/discover.rs
@@ -1,6 +1,6 @@
 //! Infrastructure for lazy project discovery. Currently only support rust-project.json discovery
 //! via a custom discover command.
-use std::{io, process::Command};
+use std::{io, path::Path};
 
 use crossbeam_channel::Sender;
 use paths::{AbsPathBuf, Utf8Path, Utf8PathBuf};
@@ -43,7 +43,11 @@ impl DiscoverCommand {
     }
 
     /// Spawn the command inside [Discover] and report progress, if any.
-    pub(crate) fn spawn(&self, discover_arg: DiscoverArgument) -> io::Result<DiscoverHandle> {
+    pub(crate) fn spawn(
+        &self,
+        discover_arg: DiscoverArgument,
+        current_dir: &Path,
+    ) -> io::Result<DiscoverHandle> {
         let command = &self.command[0];
         let args = &self.command[1..];
 
@@ -58,7 +62,7 @@ impl DiscoverCommand {
             })
             .collect();
 
-        let mut cmd = Command::new(command);
+        let mut cmd = toolchain::command(command, current_dir);
         cmd.args(args);
 
         Ok(DiscoverHandle {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs
index 53c145f884e..22f06d68d80 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/flycheck.rs
@@ -1,10 +1,11 @@
 //! Flycheck provides the functionality needed to run `cargo check` to provide
 //! LSP diagnostics based on the output of the command.
 
-use std::{fmt, io, mem, process::Command, time::Duration};
+use std::{fmt, io, process::Command, time::Duration};
 
 use cargo_metadata::PackageId;
 use crossbeam_channel::{select_biased, unbounded, Receiver, Sender};
+use ide_db::FxHashSet;
 use paths::{AbsPath, AbsPathBuf, Utf8PathBuf};
 use rustc_hash::FxHashMap;
 use serde::Deserialize as _;
@@ -27,7 +28,7 @@ pub(crate) enum InvocationStrategy {
 
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub(crate) struct CargoOptions {
-    pub(crate) target_triples: Vec<String>,
+    pub(crate) target_tuples: Vec<String>,
     pub(crate) all_targets: bool,
     pub(crate) no_default_features: bool,
     pub(crate) all_features: bool,
@@ -38,7 +39,7 @@ pub(crate) struct CargoOptions {
     pub(crate) target_dir: Option<Utf8PathBuf>,
 }
 
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub(crate) enum Target {
     Bin(String),
     Example(String),
@@ -48,7 +49,7 @@ pub(crate) enum Target {
 
 impl CargoOptions {
     pub(crate) fn apply_on_command(&self, cmd: &mut Command) {
-        for target in &self.target_triples {
+        for target in &self.target_tuples {
             cmd.args(["--target", target.as_str()]);
         }
         if self.all_targets {
@@ -231,13 +232,9 @@ struct FlycheckActor {
     command_handle: Option<CommandHandle<CargoCheckMessage>>,
     /// The receiver side of the channel mentioned above.
     command_receiver: Option<Receiver<CargoCheckMessage>>,
-    package_status: FxHashMap<Arc<PackageId>, DiagnosticReceived>,
-}
-
-#[derive(PartialEq, Eq, Copy, Clone, Debug)]
-enum DiagnosticReceived {
-    Yes,
-    No,
+    diagnostics_cleared_for: FxHashSet<Arc<PackageId>>,
+    diagnostics_cleared_for_all: bool,
+    diagnostics_received: bool,
 }
 
 #[allow(clippy::large_enum_variant)]
@@ -267,7 +264,9 @@ impl FlycheckActor {
             manifest_path,
             command_handle: None,
             command_receiver: None,
-            package_status: FxHashMap::default(),
+            diagnostics_cleared_for: Default::default(),
+            diagnostics_cleared_for_all: false,
+            diagnostics_received: false,
         }
     }
 
@@ -344,23 +343,16 @@ impl FlycheckActor {
                             error
                         );
                     }
-                    if self.package_status.is_empty() {
+                    if !self.diagnostics_received {
+                        tracing::trace!(flycheck_id = self.id, "clearing diagnostics");
                         // We finished without receiving any diagnostics.
-                        // That means all of them are stale.
+                        // Clear everything for good measure
                         self.send(FlycheckMessage::ClearDiagnostics {
                             id: self.id,
                             package_id: None,
                         });
-                    } else {
-                        for (package_id, status) in mem::take(&mut self.package_status) {
-                            if let DiagnosticReceived::No = status {
-                                self.send(FlycheckMessage::ClearDiagnostics {
-                                    id: self.id,
-                                    package_id: Some(package_id),
-                                });
-                            }
-                        }
                     }
+                    self.clear_diagnostics_state();
 
                     self.report_progress(Progress::DidFinish(res));
                 }
@@ -373,9 +365,18 @@ impl FlycheckActor {
                             "artifact received"
                         );
                         self.report_progress(Progress::DidCheckCrate(msg.target.name));
-                        self.package_status
-                            .entry(Arc::new(msg.package_id))
-                            .or_insert(DiagnosticReceived::No);
+                        let package_id = Arc::new(msg.package_id);
+                        if self.diagnostics_cleared_for.insert(package_id.clone()) {
+                            tracing::trace!(
+                                flycheck_id = self.id,
+                                package_id = package_id.repr,
+                                "clearing diagnostics"
+                            );
+                            self.send(FlycheckMessage::ClearDiagnostics {
+                                id: self.id,
+                                package_id: Some(package_id),
+                            });
+                        }
                     }
                     CargoCheckMessage::Diagnostic { diagnostic, package_id } => {
                         tracing::trace!(
@@ -384,15 +385,25 @@ impl FlycheckActor {
                             package_id = package_id.as_ref().map(|it| &it.repr),
                             "diagnostic received"
                         );
+                        self.diagnostics_received = true;
                         if let Some(package_id) = &package_id {
-                            if !self.package_status.contains_key(package_id) {
-                                self.package_status
-                                    .insert(package_id.clone(), DiagnosticReceived::Yes);
+                            if self.diagnostics_cleared_for.insert(package_id.clone()) {
+                                tracing::trace!(
+                                    flycheck_id = self.id,
+                                    package_id = package_id.repr,
+                                    "clearing diagnostics"
+                                );
                                 self.send(FlycheckMessage::ClearDiagnostics {
                                     id: self.id,
                                     package_id: Some(package_id.clone()),
                                 });
                             }
+                        } else if !self.diagnostics_cleared_for_all {
+                            self.diagnostics_cleared_for_all = true;
+                            self.send(FlycheckMessage::ClearDiagnostics {
+                                id: self.id,
+                                package_id: None,
+                            });
                         }
                         self.send(FlycheckMessage::AddDiagnostic {
                             id: self.id,
@@ -417,8 +428,14 @@ impl FlycheckActor {
             command_handle.cancel();
             self.command_receiver.take();
             self.report_progress(Progress::DidCancel);
-            self.package_status.clear();
         }
+        self.clear_diagnostics_state();
+    }
+
+    fn clear_diagnostics_state(&mut self) {
+        self.diagnostics_cleared_for.clear();
+        self.diagnostics_cleared_for_all = false;
+        self.diagnostics_received = false;
     }
 
     /// Construct a `Command` object for checking the user's code. If the user
@@ -432,12 +449,11 @@ impl FlycheckActor {
     ) -> Option<Command> {
         match &self.config {
             FlycheckConfig::CargoCommand { command, options, ansi_color_output } => {
-                let mut cmd = Command::new(Tool::Cargo.path());
+                let mut cmd = toolchain::command(Tool::Cargo.path(), &*self.root);
                 if let Some(sysroot_root) = &self.sysroot_root {
                     cmd.env("RUSTUP_TOOLCHAIN", AsRef::<std::path::Path>::as_ref(sysroot_root));
                 }
                 cmd.arg(command);
-                cmd.current_dir(&*self.root);
 
                 match package {
                     Some(pkg) => cmd.arg("-p").arg(pkg),
@@ -462,7 +478,7 @@ impl FlycheckActor {
                 if let Some(manifest_path) = &self.manifest_path {
                     cmd.arg("--manifest-path");
                     cmd.arg(manifest_path);
-                    if manifest_path.extension().map_or(false, |ext| ext == "rs") {
+                    if manifest_path.extension() == Some("rs") {
                         cmd.arg("-Zscript");
                     }
                 }
@@ -474,18 +490,15 @@ impl FlycheckActor {
                 Some(cmd)
             }
             FlycheckConfig::CustomCommand { command, args, extra_env, invocation_strategy } => {
-                let mut cmd = Command::new(command);
-                cmd.envs(extra_env);
-
-                match invocation_strategy {
-                    InvocationStrategy::Once => {
-                        cmd.current_dir(&*self.root);
-                    }
+                let root = match invocation_strategy {
+                    InvocationStrategy::Once => &*self.root,
                     InvocationStrategy::PerWorkspace => {
-                        // FIXME: cmd.current_dir(&affected_workspace);
-                        cmd.current_dir(&*self.root);
+                        // FIXME: &affected_workspace
+                        &*self.root
                     }
-                }
+                };
+                let mut cmd = toolchain::command(command, root);
+                cmd.envs(extra_env);
 
                 // If the custom command has a $saved_file placeholder, and
                 // we're saving a file, replace the placeholder in the arguments.
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 dd13bdba4cb..0f2d7823b7e 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
@@ -17,7 +17,7 @@ use parking_lot::{
     MappedRwLockReadGuard, Mutex, RwLock, RwLockReadGuard, RwLockUpgradableReadGuard,
     RwLockWriteGuard,
 };
-use proc_macro_api::ProcMacroServer;
+use proc_macro_api::ProcMacroClient;
 use project_model::{ManifestPath, ProjectWorkspace, ProjectWorkspaceKind, WorkspaceBuildScripts};
 use rustc_hash::{FxHashMap, FxHashSet};
 use tracing::{span, trace, Level};
@@ -95,7 +95,7 @@ pub(crate) struct GlobalState {
     pub(crate) last_reported_status: lsp_ext::ServerStatusParams,
 
     // proc macros
-    pub(crate) proc_macro_clients: Arc<[anyhow::Result<ProcMacroServer>]>,
+    pub(crate) proc_macro_clients: Arc<[anyhow::Result<ProcMacroClient>]>,
     pub(crate) build_deps_changed: bool,
 
     // Flycheck
@@ -726,7 +726,6 @@ impl GlobalStateSnapshot {
                     };
 
                     return Some(TargetSpec::ProjectJson(ProjectJsonTargetSpec {
-                        crate_id,
                         label: build.label,
                         target_kind: build.target_kind,
                         shell_runnables: project.runnables().to_owned(),
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs
index 2aa4ffbe1dc..ff50f7533a6 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/dispatch.rs
@@ -5,6 +5,7 @@ use std::{
 };
 
 use ide::Cancelled;
+use ide_db::base_db::ra_salsa::Cycle;
 use lsp_server::{ExtractError, Response, ResponseError};
 use serde::{de::DeserializeOwned, Serialize};
 use stdx::thread::ThreadIntent;
@@ -307,10 +308,31 @@ impl RequestDispatcher<'_> {
     }
 }
 
+#[derive(Debug)]
+enum HandlerCancelledError {
+    PropagatedPanic,
+    Inner(ide::Cancelled),
+}
+
+impl std::error::Error for HandlerCancelledError {
+    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
+        match self {
+            HandlerCancelledError::PropagatedPanic => None,
+            HandlerCancelledError::Inner(cancelled) => Some(cancelled),
+        }
+    }
+}
+
+impl fmt::Display for HandlerCancelledError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "Cancelled")
+    }
+}
+
 fn thread_result_to_response<R>(
     id: lsp_server::RequestId,
     result: thread::Result<anyhow::Result<R::Result>>,
-) -> Result<lsp_server::Response, Cancelled>
+) -> Result<lsp_server::Response, HandlerCancelledError>
 where
     R: lsp_types::request::Request,
     R::Params: DeserializeOwned,
@@ -328,7 +350,13 @@ where
             if let Some(panic_message) = panic_message {
                 message.push_str(": ");
                 message.push_str(panic_message)
-            };
+            } else if let Some(cycle) = panic.downcast_ref::<Cycle>() {
+                tracing::error!("Cycle propagated out of salsa! This is a bug: {cycle:?}");
+                return Err(HandlerCancelledError::PropagatedPanic);
+            } else if let Ok(cancelled) = panic.downcast::<Cancelled>() {
+                tracing::error!("Cancellation propagated out of salsa! This is a bug");
+                return Err(HandlerCancelledError::Inner(*cancelled));
+            }
 
             Ok(lsp_server::Response::new_err(
                 id,
@@ -342,7 +370,7 @@ where
 fn result_to_response<R>(
     id: lsp_server::RequestId,
     result: anyhow::Result<R::Result>,
-) -> Result<lsp_server::Response, Cancelled>
+) -> Result<lsp_server::Response, HandlerCancelledError>
 where
     R: lsp_types::request::Request,
     R::Params: DeserializeOwned,
@@ -353,7 +381,7 @@ where
         Err(e) => match e.downcast::<LspError>() {
             Ok(lsp_error) => lsp_server::Response::new_err(id, lsp_error.code, lsp_error.message),
             Err(e) => match e.downcast::<Cancelled>() {
-                Ok(cancelled) => return Err(cancelled),
+                Ok(cancelled) => return Err(HandlerCancelledError::Inner(cancelled)),
                 Err(e) => lsp_server::Response::new_err(
                     id,
                     lsp_server::ErrorCode::InternalError as i32,
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 c0231fd04e5..98efc637c2c 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
@@ -10,7 +10,6 @@ use lsp_types::{
     DidOpenTextDocumentParams, DidSaveTextDocumentParams, WorkDoneProgressCancelParams,
 };
 use paths::Utf8PathBuf;
-use stdx::TupleExt;
 use triomphe::Arc;
 use vfs::{AbsPathBuf, ChangeKind, VfsPath};
 
@@ -75,7 +74,6 @@ pub(crate) fn handle_did_open_text_document(
             tracing::error!("duplicate DidOpenTextDocument: {}", path);
         }
 
-        tracing::info!("New file content set {:?}", params.text_document.text);
         state.vfs.write().0.set_file_contents(path, Some(params.text_document.text.into_bytes()));
         if state.config.discover_workspace_config().is_some() {
             tracing::debug!("queuing task");
@@ -296,12 +294,11 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
         let may_flycheck_workspace = state.config.flycheck_workspace(None);
         let mut updated = false;
         let task = move || -> std::result::Result<(), ide::Cancelled> {
-            // Is the target binary? If so we let flycheck run only for the workspace that contains the crate.
             let target = TargetSpec::for_file(&world, file_id)?.and_then(|it| {
                 let tgt_kind = it.target_kind();
-                let (tgt_name, crate_id) = match it {
-                    TargetSpec::Cargo(c) => (c.target, c.crate_id),
-                    TargetSpec::ProjectJson(p) => (p.label, p.crate_id),
+                let (tgt_name, root, package) = match it {
+                    TargetSpec::Cargo(c) => (c.target, c.workspace_root, c.package),
+                    _ => return None,
                 };
 
                 let tgt = match tgt_kind {
@@ -309,28 +306,50 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
                     project_model::TargetKind::Example => Target::Example(tgt_name),
                     project_model::TargetKind::Test => Target::Test(tgt_name),
                     project_model::TargetKind::Bench => Target::Benchmark(tgt_name),
-                    _ => return None,
+                    _ => return Some((None, root, package)),
                 };
 
-                Some((tgt, crate_id))
+                Some((Some(tgt), root, package))
             });
-
-            let crate_ids = match target {
-                // Trigger flychecks for the only crate which the target belongs to
-                Some((_, krate)) => vec![krate],
-                None => {
-                    // Trigger flychecks for all workspaces that depend on the saved file
-                    // Crates containing or depending on the saved file
-                    world
-                        .analysis
-                        .crates_for(file_id)?
-                        .into_iter()
-                        .flat_map(|id| world.analysis.transitive_rev_deps(id))
-                        .flatten()
-                        .unique()
-                        .collect::<Vec<_>>()
+            tracing::debug!(?target, "flycheck target");
+            // we have a specific non-library target, attempt to only check that target, nothing
+            // else will be affected
+            if let Some((target, root, package)) = target {
+                // trigger a package check if we have a non-library target as that can't affect
+                // anything else in the workspace OR if we're not allowed to check the workspace as
+                // the user opted into package checks then
+                let package_check_allowed = target.is_some() || !may_flycheck_workspace;
+                if package_check_allowed {
+                    let workspace =
+                        world.workspaces.iter().enumerate().find(|(_, ws)| match &ws.kind {
+                            project_model::ProjectWorkspaceKind::Cargo { cargo, .. }
+                            | project_model::ProjectWorkspaceKind::DetachedFile {
+                                cargo: Some((cargo, _, _)),
+                                ..
+                            } => *cargo.workspace_root() == root,
+                            _ => false,
+                        });
+                    if let Some((idx, _)) = workspace {
+                        world.flycheck[idx].restart_for_package(package, target);
+                    }
                 }
-            };
+            }
+
+            if !may_flycheck_workspace {
+                return Ok(());
+            }
+
+            // Trigger flychecks for all workspaces that depend on the saved file
+            // Crates containing or depending on the saved file
+            let crate_ids = world
+                .analysis
+                .crates_for(file_id)?
+                .into_iter()
+                .flat_map(|id| world.analysis.transitive_rev_deps(id))
+                .flatten()
+                .unique()
+                .collect::<Vec<_>>();
+            tracing::debug!(?crate_ids, "flycheck crate ids");
             let crate_root_paths: Vec<_> = crate_ids
                 .iter()
                 .filter_map(|&crate_id| {
@@ -344,53 +363,41 @@ fn run_flycheck(state: &mut GlobalState, vfs_path: VfsPath) -> bool {
                 })
                 .collect::<ide::Cancellable<_>>()?;
             let crate_root_paths: Vec<_> = crate_root_paths.iter().map(Deref::deref).collect();
+            tracing::debug!(?crate_root_paths, "flycheck crate roots");
 
             // Find all workspaces that have at least one target containing the saved file
-            let workspace_ids = world.workspaces.iter().enumerate().filter_map(|(idx, ws)| {
-                let package = match &ws.kind {
+            let workspace_ids =
+                world.workspaces.iter().enumerate().filter(|(_, ws)| match &ws.kind {
                     project_model::ProjectWorkspaceKind::Cargo { cargo, .. }
                     | project_model::ProjectWorkspaceKind::DetachedFile {
                         cargo: Some((cargo, _, _)),
                         ..
-                    } => cargo.packages().find_map(|pkg| {
-                        let has_target_with_root = cargo[pkg]
+                    } => cargo.packages().any(|pkg| {
+                        cargo[pkg]
                             .targets
                             .iter()
-                            .any(|&it| crate_root_paths.contains(&cargo[it].root.as_path()));
-                        has_target_with_root.then(|| cargo.package_flag(&cargo[pkg]))
+                            .any(|&it| crate_root_paths.contains(&cargo[it].root.as_path()))
                     }),
-                    project_model::ProjectWorkspaceKind::Json(project) => {
-                        if !project.crates().any(|(_, krate)| {
-                            crate_root_paths.contains(&krate.root_module.as_path())
-                        }) {
-                            return None;
-                        }
-                        None
-                    }
-                    project_model::ProjectWorkspaceKind::DetachedFile { .. } => return None,
-                };
-                Some((idx, package))
-            });
+                    project_model::ProjectWorkspaceKind::Json(project) => project
+                        .crates()
+                        .any(|(_, krate)| crate_root_paths.contains(&krate.root_module.as_path())),
+                    project_model::ProjectWorkspaceKind::DetachedFile { .. } => false,
+                });
 
             let saved_file = vfs_path.as_path().map(|p| p.to_owned());
 
             // Find and trigger corresponding flychecks
             'flychecks: for flycheck in world.flycheck.iter() {
-                for (id, package) in workspace_ids.clone() {
+                for (id, _) in workspace_ids.clone() {
                     if id == flycheck.id() {
                         updated = true;
-                        if may_flycheck_workspace {
-                            flycheck.restart_workspace(saved_file.clone())
-                        } else if let Some(package) = package {
-                            flycheck
-                                .restart_for_package(package, target.clone().map(TupleExt::head))
-                        }
+                        flycheck.restart_workspace(saved_file.clone());
                         continue 'flychecks;
                     }
                 }
             }
             // No specific flycheck was triggered, so let's trigger all of them.
-            if !updated && may_flycheck_workspace {
+            if !updated {
                 for flycheck in world.flycheck.iter() {
                     flycheck.restart_workspace(saved_file.clone());
                 }
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 8f2bf80ea26..7ac70efe2d6 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
@@ -1,12 +1,7 @@
 //! This module is responsible for implementing handlers for Language Server
 //! Protocol. This module specifically handles requests.
 
-use std::{
-    fs,
-    io::Write as _,
-    ops::Not,
-    process::{self, Stdio},
-};
+use std::{fs, io::Write as _, ops::Not, process::Stdio};
 
 use anyhow::Context;
 
@@ -32,7 +27,7 @@ use paths::Utf8PathBuf;
 use project_model::{CargoWorkspace, ManifestPath, ProjectWorkspaceKind, TargetKind};
 use serde_json::json;
 use stdx::{format_to, never};
-use syntax::{algo, ast, AstNode, TextRange, TextSize};
+use syntax::{TextRange, TextSize};
 use triomphe::Arc;
 use vfs::{AbsPath, AbsPathBuf, FileId, VfsPath};
 
@@ -933,39 +928,32 @@ pub(crate) fn handle_runnables(
     let offset = params.position.and_then(|it| from_proto::offset(&line_index, it).ok());
     let target_spec = TargetSpec::for_file(&snap, file_id)?;
 
-    let expect_test = match offset {
-        Some(offset) => {
-            let source_file = snap.analysis.parse(file_id)?;
-            algo::find_node_at_offset::<ast::MacroCall>(source_file.syntax(), offset)
-                .and_then(|it| it.path()?.segment()?.name_ref())
-                .map_or(false, |it| it.text() == "expect" || it.text() == "expect_file")
-        }
-        None => false,
-    };
-
     let mut res = Vec::new();
     for runnable in snap.analysis.runnables(file_id)? {
-        if should_skip_for_offset(&runnable, offset) {
-            continue;
-        }
-        if should_skip_target(&runnable, target_spec.as_ref()) {
+        if should_skip_for_offset(&runnable, offset)
+            || should_skip_target(&runnable, target_spec.as_ref())
+        {
             continue;
         }
+
+        let update_test = runnable.update_test;
         if let Some(mut runnable) = to_proto::runnable(&snap, runnable)? {
-            if expect_test {
-                if let lsp_ext::RunnableArgs::Cargo(r) = &mut runnable.args {
-                    runnable.label = format!("{} + expect", runnable.label);
-                    r.environment.insert("UPDATE_EXPECT".to_owned(), "1".to_owned());
-                    if let Some(TargetSpec::Cargo(CargoTargetSpec {
-                        sysroot_root: Some(sysroot_root),
-                        ..
-                    })) = &target_spec
-                    {
-                        r.environment
-                            .insert("RUSTC_TOOLCHAIN".to_owned(), sysroot_root.to_string());
-                    }
-                }
+            if let Some(runnable) =
+                to_proto::make_update_runnable(&runnable, &update_test.label(), &update_test.env())
+            {
+                res.push(runnable);
             }
+
+            if let lsp_ext::RunnableArgs::Cargo(r) = &mut runnable.args {
+                if let Some(TargetSpec::Cargo(CargoTargetSpec {
+                    sysroot_root: Some(sysroot_root),
+                    ..
+                })) = &target_spec
+                {
+                    r.environment.insert("RUSTC_TOOLCHAIN".to_owned(), sysroot_root.to_string());
+                }
+            };
+
             res.push(runnable);
         }
     }
@@ -1831,6 +1819,7 @@ pub(crate) fn handle_call_hierarchy_outgoing(
     let doc = TextDocumentIdentifier::new(item.uri);
     let frange = from_proto::file_range(&snap, &doc, item.selection_range)?;
     let fpos = FilePosition { file_id: frange.file_id, offset: frange.range.start() };
+    let line_index = snap.file_line_index(fpos.file_id)?;
 
     let config = snap.config.call_hierarchy();
     let call_items = match snap.analysis.outgoing_calls(config, fpos)? {
@@ -1841,8 +1830,6 @@ pub(crate) fn handle_call_hierarchy_outgoing(
     let mut res = vec![];
 
     for call_item in call_items.into_iter() {
-        let file_id = call_item.target.file_id;
-        let line_index = snap.file_line_index(file_id)?;
         let item = to_proto::call_hierarchy_item(&snap, call_item.target)?;
         res.push(CallHierarchyOutgoingCall {
             to: item,
@@ -2148,6 +2135,7 @@ fn runnable_action_links(
     }
 
     let title = runnable.title();
+    let update_test = runnable.update_test;
     let r = to_proto::runnable(snap, runnable).ok()??;
 
     let mut group = lsp_ext::CommandLinkGroup::default();
@@ -2159,7 +2147,15 @@ fn runnable_action_links(
 
     if hover_actions_config.debug && client_commands_config.debug_single {
         let dbg_command = to_proto::command::debug_single(&r);
-        group.commands.push(to_command_link(dbg_command, r.label));
+        group.commands.push(to_command_link(dbg_command, r.label.clone()));
+    }
+
+    if hover_actions_config.update_test && client_commands_config.run_single {
+        let label = update_test.label();
+        if let Some(r) = to_proto::make_update_runnable(&r, &label, &update_test.env()) {
+            let update_command = to_proto::command::run_single(&r, label.unwrap().as_str());
+            group.commands.push(to_command_link(update_command, r.label.clone()));
+        }
     }
 
     Some(group)
@@ -2243,10 +2239,31 @@ fn run_rustfmt(
     let line_index = snap.file_line_index(file_id)?;
     let source_root_id = snap.analysis.source_root_id(file_id).ok();
 
+    // try to chdir to the file so we can respect `rustfmt.toml`
+    // FIXME: use `rustfmt --config-path` once
+    // https://github.com/rust-lang/rustfmt/issues/4660 gets fixed
+    let current_dir = match text_document.uri.to_file_path() {
+        Ok(mut path) => {
+            // pop off file name
+            if path.pop() && path.is_dir() {
+                path
+            } else {
+                std::env::current_dir()?
+            }
+        }
+        Err(_) => {
+            tracing::error!(
+                text_document = ?text_document.uri,
+                "Unable to get path, rustfmt.toml might be ignored"
+            );
+            std::env::current_dir()?
+        }
+    };
+
     let mut command = match snap.config.rustfmt(source_root_id) {
         RustfmtConfig::Rustfmt { extra_args, enable_range_formatting } => {
             // FIXME: Set RUSTUP_TOOLCHAIN
-            let mut cmd = process::Command::new(toolchain::Tool::Rustfmt.path());
+            let mut cmd = toolchain::command(toolchain::Tool::Rustfmt.path(), current_dir);
             cmd.envs(snap.config.extra_env(source_root_id));
             cmd.args(extra_args);
 
@@ -2300,9 +2317,9 @@ fn run_rustfmt(
                     } else {
                         cmd
                     };
-                    process::Command::new(cmd_path)
+                    toolchain::command(cmd_path, current_dir)
                 }
-                _ => process::Command::new(cmd),
+                _ => toolchain::command(cmd, current_dir),
             };
 
             cmd.envs(snap.config.extra_env(source_root_id));
@@ -2313,24 +2330,6 @@ fn run_rustfmt(
 
     tracing::debug!(?command, "created format command");
 
-    // try to chdir to the file so we can respect `rustfmt.toml`
-    // FIXME: use `rustfmt --config-path` once
-    // https://github.com/rust-lang/rustfmt/issues/4660 gets fixed
-    match text_document.uri.to_file_path() {
-        Ok(mut path) => {
-            // pop off file name
-            if path.pop() && path.is_dir() {
-                command.current_dir(path);
-            }
-        }
-        Err(_) => {
-            tracing::error!(
-                text_document = ?text_document.uri,
-                "Unable to get path, rustfmt.toml might be ignored"
-            );
-        }
-    }
-
     let mut rustfmt = command
         .stdin(Stdio::piped())
         .stdout(Stdio::piped())
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 8946c7acb93..fcfd06679bf 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
@@ -174,6 +174,8 @@ fn integrated_completion_benchmark() {
             limit: None,
             add_semicolon_to_unit: true,
             fields_to_resolve: CompletionFieldsToResolve::empty(),
+            exclude_flyimport: vec![],
+            exclude_traits: &[],
         };
         let position =
             FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
@@ -222,6 +224,8 @@ fn integrated_completion_benchmark() {
             limit: None,
             add_semicolon_to_unit: true,
             fields_to_resolve: CompletionFieldsToResolve::empty(),
+            exclude_flyimport: vec![],
+            exclude_traits: &[],
         };
         let position =
             FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
@@ -268,6 +272,8 @@ fn integrated_completion_benchmark() {
             limit: None,
             add_semicolon_to_unit: true,
             fields_to_resolve: CompletionFieldsToResolve::empty(),
+            exclude_flyimport: vec![],
+            exclude_traits: &[],
         };
         let position =
             FilePosition { file_id, offset: TextSize::try_from(completion_offset).unwrap() };
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 c0173d9c247..f50cbba7acf 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
@@ -1,5 +1,9 @@
 //! rust-analyzer extensions to the LSP.
 
+// Note when adding new resolve payloads, add a #[serde(default)] on boolean fields as some clients
+// might strip `false` values from the JSON payload due to their reserialization logic turning false
+// into null which will then cause them to be omitted in the resolve request. See https://github.com/rust-lang/rust-analyzer/issues/18767
+
 #![allow(clippy::disallowed_types)]
 
 use std::ops;
@@ -427,14 +431,14 @@ impl Request for Runnables {
     const METHOD: &'static str = "experimental/runnables";
 }
 
-#[derive(Serialize, Deserialize, Debug)]
+#[derive(Serialize, Deserialize, Debug, Clone)]
 #[serde(rename_all = "camelCase")]
 pub struct RunnablesParams {
     pub text_document: TextDocumentIdentifier,
     pub position: Option<Position>,
 }
 
-#[derive(Deserialize, Serialize, Debug)]
+#[derive(Deserialize, Serialize, Debug, Clone)]
 #[serde(rename_all = "camelCase")]
 pub struct Runnable {
     pub label: String,
@@ -444,7 +448,7 @@ pub struct Runnable {
     pub args: RunnableArgs,
 }
 
-#[derive(Deserialize, Serialize, Debug)]
+#[derive(Deserialize, Serialize, Debug, Clone)]
 #[serde(rename_all = "camelCase")]
 #[serde(untagged)]
 pub enum RunnableArgs {
@@ -452,14 +456,14 @@ pub enum RunnableArgs {
     Shell(ShellRunnableArgs),
 }
 
-#[derive(Serialize, Deserialize, Debug)]
+#[derive(Serialize, Deserialize, Debug, Clone)]
 #[serde(rename_all = "lowercase")]
 pub enum RunnableKind {
     Cargo,
     Shell,
 }
 
-#[derive(Deserialize, Serialize, Debug)]
+#[derive(Deserialize, Serialize, Debug, Clone)]
 #[serde(rename_all = "camelCase")]
 pub struct CargoRunnableArgs {
     #[serde(skip_serializing_if = "FxHashMap::is_empty")]
@@ -475,7 +479,7 @@ pub struct CargoRunnableArgs {
     pub executable_args: Vec<String>,
 }
 
-#[derive(Deserialize, Serialize, Debug)]
+#[derive(Deserialize, Serialize, Debug, Clone)]
 #[serde(rename_all = "camelCase")]
 pub struct ShellRunnableArgs {
     #[serde(skip_serializing_if = "FxHashMap::is_empty")]
@@ -829,6 +833,7 @@ pub struct CompletionResolveData {
     pub version: Option<i32>,
     #[serde(skip_serializing_if = "Option::is_none", default)]
     pub trigger_character: Option<char>,
+    #[serde(default)]
     pub for_ref: bool,
     pub hash: String,
 }
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 05e93b4e6ac..fe4d02dcb4f 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
@@ -20,6 +20,7 @@ use itertools::Itertools;
 use paths::{Utf8Component, Utf8Prefix};
 use semver::VersionReq;
 use serde_json::to_value;
+use syntax::SmolStr;
 use vfs::AbsPath;
 
 use crate::{
@@ -560,8 +561,7 @@ pub(crate) fn inlay_hint(
     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))
+        .is_none_or(|version| VersionReq::parse(">=1.86.0").unwrap().matches(version))
         && resolve_range_and_hash.is_some()
         && fields_to_resolve.resolve_text_edits
     {
@@ -1567,6 +1567,7 @@ pub(crate) fn code_lens(
             let line_index = snap.file_line_index(run.nav.file_id)?;
             let annotation_range = range(&line_index, annotation.range);
 
+            let update_test = run.update_test;
             let title = run.title();
             let can_debug = match run.kind {
                 ide::RunnableKind::DocTest { .. } => false,
@@ -1602,6 +1603,18 @@ pub(crate) fn code_lens(
                             data: None,
                         })
                     }
+                    if lens_config.update_test && client_commands_config.run_single {
+                        let label = update_test.label();
+                        let env = update_test.env();
+                        if let Some(r) = make_update_runnable(&r, &label, &env) {
+                            let command = command::run_single(&r, label.unwrap().as_str());
+                            acc.push(lsp_types::CodeLens {
+                                range: annotation_range,
+                                command: Some(command),
+                                data: None,
+                            })
+                        }
+                    }
                 }
 
                 if lens_config.interpret {
@@ -1786,7 +1799,7 @@ pub(crate) mod command {
 
     pub(crate) fn debug_single(runnable: &lsp_ext::Runnable) -> lsp_types::Command {
         lsp_types::Command {
-            title: "Debug".into(),
+            title: "âš™\u{fe0e} Debug".into(),
             command: "rust-analyzer.debugSingle".into(),
             arguments: Some(vec![to_value(runnable).unwrap()]),
         }
@@ -1838,6 +1851,28 @@ pub(crate) mod command {
     }
 }
 
+pub(crate) fn make_update_runnable(
+    runnable: &lsp_ext::Runnable,
+    label: &Option<SmolStr>,
+    env: &[(&str, &str)],
+) -> Option<lsp_ext::Runnable> {
+    if !matches!(runnable.args, lsp_ext::RunnableArgs::Cargo(_)) {
+        return None;
+    }
+    let label = label.as_ref()?;
+
+    let mut runnable = runnable.clone();
+    runnable.label = format!("{} + {}", runnable.label, label);
+
+    let lsp_ext::RunnableArgs::Cargo(r) = &mut runnable.args else {
+        unreachable!();
+    };
+
+    r.environment.extend(env.iter().map(|(k, v)| (k.to_string(), v.to_string())));
+
+    Some(runnable)
+}
+
 pub(crate) fn implementation_title(count: usize) -> String {
     if count == 1 {
         "1 implementation".into()
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
index d97d96d54a0..97657b92658 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
@@ -744,7 +744,8 @@ impl GlobalState {
                             DiscoverProjectParam::Path(it) => DiscoverArgument::Path(it),
                         };
 
-                        let handle = discover.spawn(arg).unwrap();
+                        let handle =
+                            discover.spawn(arg, &std::env::current_dir().unwrap()).unwrap();
                         self.discover_handle = Some(handle);
                     }
                 }
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 3444773695b..0add2cdf5a7 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
@@ -24,7 +24,7 @@ use ide_db::{
 use itertools::Itertools;
 use load_cargo::{load_proc_macro, ProjectFolders};
 use lsp_types::FileSystemWatcher;
-use proc_macro_api::ProcMacroServer;
+use proc_macro_api::ProcMacroClient;
 use project_model::{ManifestPath, ProjectWorkspace, ProjectWorkspaceKind, WorkspaceBuildScripts};
 use stdx::{format_to, thread::ThreadIntent};
 use triomphe::Arc;
@@ -630,13 +630,10 @@ impl GlobalState {
                 };
 
                 let env: FxHashMap<_, _> = match &ws.kind {
-                    ProjectWorkspaceKind::Cargo { cargo_config_extra_env, .. }
-                    | ProjectWorkspaceKind::DetachedFile {
-                        cargo: Some(_),
-                        cargo_config_extra_env,
-                        ..
-                    } => cargo_config_extra_env
-                        .iter()
+                    ProjectWorkspaceKind::Cargo { cargo, .. }
+                    | ProjectWorkspaceKind::DetachedFile { cargo: Some((cargo, ..)), .. } => cargo
+                        .env()
+                        .into_iter()
                         .chain(self.config.extra_env(None))
                         .map(|(a, b)| (a.clone(), b.clone()))
                         .chain(
@@ -650,7 +647,7 @@ impl GlobalState {
                 };
                 info!("Using proc-macro server at {path}");
 
-                ProcMacroServer::spawn(&path, &env).map_err(|err| {
+                ProcMacroClient::spawn(&path, &env).map_err(|err| {
                     tracing::error!(
                         "Failed to run proc-macro server from path {path}, error: {err:?}",
                     );
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs
index b4aa73d2780..b28567fe09b 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/target_spec.rs
@@ -62,7 +62,6 @@ pub(crate) struct CargoTargetSpec {
 
 #[derive(Clone, Debug)]
 pub(crate) struct ProjectJsonTargetSpec {
-    pub(crate) crate_id: CrateId,
     pub(crate) label: String,
     pub(crate) target_kind: TargetKind,
     pub(crate) shell_runnables: Vec<Runnable>,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/test_runner.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/test_runner.rs
index 2fd52547336..503b3ee43a1 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/test_runner.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/test_runner.rs
@@ -1,8 +1,6 @@
 //! This module provides the functionality needed to run `cargo test` in a background
 //! thread and report the result of each test in a channel.
 
-use std::process::Command;
-
 use crossbeam_channel::Sender;
 use paths::AbsPath;
 use serde::Deserialize as _;
@@ -78,7 +76,7 @@ impl CargoTestHandle {
         test_target: TestTarget,
         sender: Sender<CargoTestMessage>,
     ) -> std::io::Result<Self> {
-        let mut cmd = Command::new(Tool::Cargo.path());
+        let mut cmd = toolchain::command(Tool::Cargo.path(), root);
         cmd.env("RUSTC_BOOTSTRAP", "1");
         cmd.arg("test");
 
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 c1ca5960637..2b3c0a47a22 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
@@ -1082,11 +1082,11 @@ fn resolve_proc_macro() {
         return;
     }
 
-    let sysroot = project_model::Sysroot::discover(
+    let mut sysroot = project_model::Sysroot::discover(
         &AbsPathBuf::assert_utf8(std::env::current_dir().unwrap()),
         &Default::default(),
-        project_model::SysrootQueryMetadata::CargoMetadata,
     );
+    sysroot.load_workspace(&project_model::SysrootSourceWorkspaceConfig::default_cargo());
 
     let proc_macro_server_path = sysroot.discover_proc_macro_srv().unwrap();
 
diff --git a/src/tools/rust-analyzer/crates/span/src/lib.rs b/src/tools/rust-analyzer/crates/span/src/lib.rs
index 20c3b087af5..8dc95735038 100644
--- a/src/tools/rust-analyzer/crates/span/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/span/src/lib.rs
@@ -358,6 +358,18 @@ impl HirFileId {
     }
 }
 
+/// Legacy span type, only defined here as it is still used by the proc-macro server.
+/// While rust-analyzer doesn't use this anymore at all, RustRover relies on the legacy type for
+/// proc-macro expansion.
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
+pub struct TokenId(pub u32);
+
+impl std::fmt::Debug for TokenId {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
 #[cfg(not(feature = "ra-salsa"))]
 mod intern_id_proxy {
     use std::fmt;
diff --git a/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs b/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs
index 3a05b83e497..ed8b1908d60 100644
--- a/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/syntax-bridge/src/lib.rs
@@ -5,17 +5,14 @@ use std::fmt;
 use intern::Symbol;
 use rustc_hash::{FxHashMap, FxHashSet};
 use span::{Edition, SpanAnchor, SpanData, SpanMap};
-use stdx::{format_to, never, non_empty_vec::NonEmptyVec};
+use stdx::{format_to, never};
 use syntax::{
     ast::{self, make::tokens::doc_comment},
     format_smolstr, AstToken, Parse, PreorderWithTokens, SmolStr, SyntaxElement,
     SyntaxKind::{self, *},
     SyntaxNode, SyntaxToken, SyntaxTreeBuilder, TextRange, TextSize, WalkEvent, T,
 };
-use tt::{
-    buffer::{Cursor, TokenBuffer},
-    token_to_literal,
-};
+use tt::{buffer::Cursor, token_to_literal};
 
 pub mod prettify_macro_expansion;
 mod to_parser_input;
@@ -99,7 +96,7 @@ pub fn syntax_node_to_token_tree<Ctx, SpanMap>(
     map: SpanMap,
     span: SpanData<Ctx>,
     mode: DocCommentDesugarMode,
-) -> tt::Subtree<SpanData<Ctx>>
+) -> tt::TopSubtree<SpanData<Ctx>>
 where
     SpanData<Ctx>: Copy + fmt::Debug,
     SpanMap: SpanMapper<SpanData<Ctx>>,
@@ -118,7 +115,7 @@ pub fn syntax_node_to_token_tree_modified<Ctx, SpanMap>(
     remove: FxHashSet<SyntaxElement>,
     call_site: SpanData<Ctx>,
     mode: DocCommentDesugarMode,
-) -> tt::Subtree<SpanData<Ctx>>
+) -> tt::TopSubtree<SpanData<Ctx>>
 where
     SpanMap: SpanMapper<SpanData<Ctx>>,
     SpanData<Ctx>: Copy + fmt::Debug,
@@ -142,7 +139,7 @@ where
 /// Converts a [`tt::Subtree`] back to a [`SyntaxNode`].
 /// The produced `SpanMap` contains a mapping from the syntax nodes offsets to the subtree's spans.
 pub fn token_tree_to_syntax_node<Ctx>(
-    tt: &tt::Subtree<SpanData<Ctx>>,
+    tt: &tt::TopSubtree<SpanData<Ctx>>,
     entry_point: parser::TopEntryPoint,
     edition: parser::Edition,
 ) -> (Parse<SyntaxNode>, SpanMap<Ctx>)
@@ -150,16 +147,10 @@ where
     SpanData<Ctx>: Copy + fmt::Debug,
     Ctx: PartialEq,
 {
-    let buffer = match tt {
-        tt::Subtree {
-            delimiter: tt::Delimiter { kind: tt::DelimiterKind::Invisible, .. },
-            token_trees,
-        } => TokenBuffer::from_tokens(token_trees),
-        _ => TokenBuffer::from_subtree(tt),
-    };
-    let parser_input = to_parser_input(edition, &buffer);
+    let buffer = tt.view().strip_invisible();
+    let parser_input = to_parser_input(edition, buffer);
     let parser_output = entry_point.parse(&parser_input, edition);
-    let mut tree_sink = TtTreeSink::new(buffer.begin());
+    let mut tree_sink = TtTreeSink::new(buffer.cursor());
     for event in parser_output.iter() {
         match event {
             parser::Step::Token { kind, n_input_tokens: n_raw_tokens } => {
@@ -183,7 +174,7 @@ pub fn parse_to_token_tree<Ctx>(
     anchor: SpanAnchor,
     ctx: Ctx,
     text: &str,
-) -> Option<tt::Subtree<SpanData<Ctx>>>
+) -> Option<tt::TopSubtree<SpanData<Ctx>>>
 where
     SpanData<Ctx>: Copy + fmt::Debug,
     Ctx: Copy,
@@ -202,7 +193,7 @@ pub fn parse_to_token_tree_static_span<S>(
     edition: Edition,
     span: S,
     text: &str,
-) -> Option<tt::Subtree<S>>
+) -> Option<tt::TopSubtree<S>>
 where
     S: Copy + fmt::Debug,
 {
@@ -215,47 +206,38 @@ where
     Some(convert_tokens(&mut conv))
 }
 
-fn convert_tokens<S, C>(conv: &mut C) -> tt::Subtree<S>
+fn convert_tokens<S, C>(conv: &mut C) -> tt::TopSubtree<S>
 where
     C: TokenConverter<S>,
     S: Copy + fmt::Debug,
     C::Token: fmt::Debug,
 {
-    let entry = tt::SubtreeBuilder {
-        delimiter: tt::Delimiter::invisible_spanned(conv.call_site()),
-        token_trees: vec![],
-    };
-    let mut stack = NonEmptyVec::new(entry);
+    let mut builder =
+        tt::TopSubtreeBuilder::new(tt::Delimiter::invisible_spanned(conv.call_site()));
 
     while let Some((token, abs_range)) = conv.bump() {
-        let tt::SubtreeBuilder { delimiter, token_trees } = stack.last_mut();
-
+        let delimiter = builder.expected_delimiter().map(|it| it.kind);
         let tt = match token.as_leaf() {
-            Some(leaf) => tt::TokenTree::Leaf(leaf.clone()),
+            Some(leaf) => leaf.clone(),
             None => match token.kind(conv) {
                 // Desugar doc comments into doc attributes
                 COMMENT => {
                     let span = conv.span_for(abs_range);
-                    if let Some(tokens) = conv.convert_doc_comment(&token, span) {
-                        token_trees.extend(tokens);
-                    }
+                    conv.convert_doc_comment(&token, span, &mut builder);
                     continue;
                 }
                 kind if kind.is_punct() && kind != UNDERSCORE => {
-                    let expected = match delimiter.kind {
-                        tt::DelimiterKind::Parenthesis => Some(T![')']),
-                        tt::DelimiterKind::Brace => Some(T!['}']),
-                        tt::DelimiterKind::Bracket => Some(T![']']),
-                        tt::DelimiterKind::Invisible => None,
+                    let expected = match delimiter {
+                        Some(tt::DelimiterKind::Parenthesis) => Some(T![')']),
+                        Some(tt::DelimiterKind::Brace) => Some(T!['}']),
+                        Some(tt::DelimiterKind::Bracket) => Some(T![']']),
+                        Some(tt::DelimiterKind::Invisible) | None => None,
                     };
 
                     // Current token is a closing delimiter that we expect, fix up the closing span
                     // and end the subtree here
                     if matches!(expected, Some(expected) if expected == kind) {
-                        if let Some(mut subtree) = stack.pop() {
-                            subtree.delimiter.close = conv.span_for(abs_range);
-                            stack.last_mut().token_trees.push(subtree.build().into());
-                        }
+                        builder.close(conv.span_for(abs_range));
                         continue;
                     }
 
@@ -268,16 +250,7 @@ where
 
                     // Start a new subtree
                     if let Some(kind) = delim {
-                        let open = conv.span_for(abs_range);
-                        stack.push(tt::SubtreeBuilder {
-                            delimiter: tt::Delimiter {
-                                open,
-                                // will be overwritten on subtree close above
-                                close: open,
-                                kind,
-                            },
-                            token_trees: vec![],
-                        });
+                        builder.open(kind, conv.span_for(abs_range));
                         continue;
                     }
 
@@ -289,7 +262,6 @@ where
                         panic!("Token from lexer must be single char: token = {token:#?}")
                     };
                     tt::Leaf::from(tt::Punct { char, spacing, span: conv.span_for(abs_range) })
-                        .into()
                 }
                 kind => {
                     macro_rules! make_ident {
@@ -320,7 +292,7 @@ where
                                 span: conv
                                     .span_for(TextRange::at(abs_range.start(), TextSize::of('\''))),
                             });
-                            token_trees.push(apostrophe.into());
+                            builder.push(apostrophe);
 
                             let ident = tt::Leaf::from(tt::Ident {
                                 sym: Symbol::intern(&token.to_text(conv)[1..]),
@@ -330,47 +302,26 @@ where
                                 )),
                                 is_raw: tt::IdentIsRaw::No,
                             });
-                            token_trees.push(ident.into());
+                            builder.push(ident);
                             continue;
                         }
                         _ => continue,
                     };
 
-                    leaf.into()
+                    leaf
                 }
             },
         };
 
-        token_trees.push(tt);
+        builder.push(tt);
     }
 
     // If we get here, we've consumed all input tokens.
     // We might have more than one subtree in the stack, if the delimiters are improperly balanced.
     // Merge them so we're left with one.
-    while let Some(entry) = stack.pop() {
-        let parent = stack.last_mut();
-
-        let leaf: tt::Leaf<_> = tt::Punct {
-            span: entry.delimiter.open,
-            char: match entry.delimiter.kind {
-                tt::DelimiterKind::Parenthesis => '(',
-                tt::DelimiterKind::Brace => '{',
-                tt::DelimiterKind::Bracket => '[',
-                tt::DelimiterKind::Invisible => '$',
-            },
-            spacing: tt::Spacing::Alone,
-        }
-        .into();
-        parent.token_trees.push(leaf.into());
-        parent.token_trees.extend(entry.token_trees);
-    }
+    builder.flatten_unclosed_subtrees();
 
-    let subtree = stack.into_last().build();
-    if let [tt::TokenTree::Subtree(first)] = &*subtree.token_trees {
-        first.clone()
-    } else {
-        subtree
-    }
+    builder.build_skip_top_subtree()
 }
 
 fn is_single_token_op(kind: SyntaxKind) -> bool {
@@ -436,25 +387,17 @@ fn convert_doc_comment<S: Copy>(
     token: &syntax::SyntaxToken,
     span: S,
     mode: DocCommentDesugarMode,
-) -> Option<Vec<tt::TokenTree<S>>> {
-    let comment = ast::Comment::cast(token.clone())?;
-    let doc = comment.kind().doc?;
+    builder: &mut tt::TopSubtreeBuilder<S>,
+) {
+    let Some(comment) = ast::Comment::cast(token.clone()) else { return };
+    let Some(doc) = comment.kind().doc else { return };
 
     let mk_ident = |s: &str| {
-        tt::TokenTree::from(tt::Leaf::from(tt::Ident {
-            sym: Symbol::intern(s),
-            span,
-            is_raw: tt::IdentIsRaw::No,
-        }))
+        tt::Leaf::from(tt::Ident { sym: Symbol::intern(s), span, is_raw: tt::IdentIsRaw::No })
     };
 
-    let mk_punct = |c: char| {
-        tt::TokenTree::from(tt::Leaf::from(tt::Punct {
-            char: c,
-            spacing: tt::Spacing::Alone,
-            span,
-        }))
-    };
+    let mk_punct =
+        |c: char| tt::Leaf::from(tt::Punct { char: c, spacing: tt::Spacing::Alone, span });
 
     let mk_doc_literal = |comment: &ast::Comment| {
         let prefix_len = comment.prefix().len();
@@ -467,24 +410,20 @@ fn convert_doc_comment<S: Copy>(
         let (text, kind) = desugar_doc_comment_text(text, mode);
         let lit = tt::Literal { symbol: text, span, kind, suffix: None };
 
-        tt::TokenTree::from(tt::Leaf::from(lit))
+        tt::Leaf::from(lit)
     };
 
     // Make `doc="\" Comments\""
-    let meta_tkns = Box::new([mk_ident("doc"), mk_punct('='), mk_doc_literal(&comment)]);
+    let meta_tkns = [mk_ident("doc"), mk_punct('='), mk_doc_literal(&comment)];
 
     // Make `#![]`
-    let mut token_trees = Vec::with_capacity(3);
-    token_trees.push(mk_punct('#'));
+    builder.push(mk_punct('#'));
     if let ast::CommentPlacement::Inner = doc {
-        token_trees.push(mk_punct('!'));
+        builder.push(mk_punct('!'));
     }
-    token_trees.push(tt::TokenTree::from(tt::Subtree {
-        delimiter: tt::Delimiter { open: span, close: span, kind: tt::DelimiterKind::Bracket },
-        token_trees: meta_tkns,
-    }));
-
-    Some(token_trees)
+    builder.open(tt::DelimiterKind::Bracket, span);
+    builder.extend(meta_tkns);
+    builder.close(span);
 }
 
 /// A raw token (straight from lexer) converter
@@ -518,7 +457,12 @@ trait SrcToken<Ctx, S> {
 trait TokenConverter<S>: Sized {
     type Token: SrcToken<Self, S>;
 
-    fn convert_doc_comment(&self, token: &Self::Token, span: S) -> Option<Vec<tt::TokenTree<S>>>;
+    fn convert_doc_comment(
+        &self,
+        token: &Self::Token,
+        span: S,
+        builder: &mut tt::TopSubtreeBuilder<S>,
+    );
 
     fn bump(&mut self) -> Option<(Self::Token, TextRange)>;
 
@@ -567,9 +511,10 @@ where
         &self,
         &token: &usize,
         span: SpanData<Ctx>,
-    ) -> Option<Vec<tt::TokenTree<SpanData<Ctx>>>> {
+        builder: &mut tt::TopSubtreeBuilder<SpanData<Ctx>>,
+    ) {
         let text = self.lexed.text(token);
-        convert_doc_comment(&doc_comment(text), span, self.mode)
+        convert_doc_comment(&doc_comment(text), span, self.mode, builder);
     }
 
     fn bump(&mut self) -> Option<(Self::Token, TextRange)> {
@@ -606,9 +551,9 @@ where
 {
     type Token = usize;
 
-    fn convert_doc_comment(&self, &token: &usize, span: S) -> Option<Vec<tt::TokenTree<S>>> {
+    fn convert_doc_comment(&self, &token: &usize, span: S, builder: &mut tt::TopSubtreeBuilder<S>) {
         let text = self.lexed.text(token);
-        convert_doc_comment(&doc_comment(text), span, self.mode)
+        convert_doc_comment(&doc_comment(text), span, self.mode, builder);
     }
 
     fn bump(&mut self) -> Option<(Self::Token, TextRange)> {
@@ -773,8 +718,13 @@ where
     SpanMap: SpanMapper<S>,
 {
     type Token = SynToken<S>;
-    fn convert_doc_comment(&self, token: &Self::Token, span: S) -> Option<Vec<tt::TokenTree<S>>> {
-        convert_doc_comment(token.token(), span, self.mode)
+    fn convert_doc_comment(
+        &self,
+        token: &Self::Token,
+        span: S,
+        builder: &mut tt::TopSubtreeBuilder<S>,
+    ) {
+        convert_doc_comment(token.token(), span, self.mode, builder);
     }
 
     fn bump(&mut self) -> Option<(Self::Token, TextRange)> {
@@ -899,15 +849,12 @@ where
     /// This occurs when a float literal is used as a field access.
     fn float_split(&mut self, has_pseudo_dot: bool) {
         let (text, span) = match self.cursor.token_tree() {
-            Some(tt::buffer::TokenTreeRef::Leaf(
-                tt::Leaf::Literal(tt::Literal {
-                    symbol: text,
-                    span,
-                    kind: tt::LitKind::Float,
-                    suffix: _,
-                }),
-                _,
-            )) => (text.as_str(), *span),
+            Some(tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
+                symbol: text,
+                span,
+                kind: tt::LitKind::Float,
+                suffix: _,
+            }))) => (text.as_str(), *span),
             tt => unreachable!("{tt:?}"),
         };
         // FIXME: Span splitting
@@ -942,7 +889,7 @@ where
             }
             None => unreachable!(),
         }
-        self.cursor = self.cursor.bump();
+        self.cursor.bump();
     }
 
     fn token(&mut self, kind: SyntaxKind, mut n_tokens: u8) {
@@ -950,24 +897,24 @@ where
             n_tokens = 2;
         }
 
-        let mut last = self.cursor;
+        let mut last_two = self.cursor.peek_two_leaves();
         let mut combined_span = None;
         'tokens: for _ in 0..n_tokens {
             let tmp: u8;
             if self.cursor.eof() {
                 break;
             }
-            last = self.cursor;
+            last_two = self.cursor.peek_two_leaves();
             let (text, span) = loop {
                 break match self.cursor.token_tree() {
-                    Some(tt::buffer::TokenTreeRef::Leaf(leaf, _)) => match leaf {
+                    Some(tt::TokenTree::Leaf(leaf)) => match leaf {
                         tt::Leaf::Ident(ident) => {
                             if ident.is_raw.yes() {
                                 self.buf.push_str("r#");
                                 self.text_pos += TextSize::of("r#");
                             }
                             let r = (ident.sym.as_str(), ident.span);
-                            self.cursor = self.cursor.bump();
+                            self.cursor.bump();
                             r
                         }
                         tt::Leaf::Punct(punct) => {
@@ -977,7 +924,7 @@ where
                                 std::str::from_utf8(std::slice::from_ref(&tmp)).unwrap(),
                                 punct.span,
                             );
-                            self.cursor = self.cursor.bump();
+                            self.cursor.bump();
                             r
                         }
                         tt::Leaf::Literal(lit) => {
@@ -989,20 +936,19 @@ where
                                 None => Some(lit.span),
                                 Some(prev_span) => Some(Self::merge_spans(prev_span, lit.span)),
                             };
-                            self.cursor = self.cursor.bump();
+                            self.cursor.bump();
                             continue 'tokens;
                         }
                     },
-                    Some(tt::buffer::TokenTreeRef::Subtree(subtree, _)) => {
-                        self.cursor = self.cursor.subtree().unwrap();
+                    Some(tt::TokenTree::Subtree(subtree)) => {
+                        self.cursor.bump();
                         match delim_to_str(subtree.delimiter.kind, false) {
                             Some(it) => (it, subtree.delimiter.open),
                             None => continue,
                         }
                     }
                     None => {
-                        let parent = self.cursor.end().unwrap();
-                        self.cursor = self.cursor.bump();
+                        let parent = self.cursor.end();
                         match delim_to_str(parent.delimiter.kind, true) {
                             Some(it) => (it, parent.delimiter.close),
                             None => continue,
@@ -1023,12 +969,7 @@ where
         self.buf.clear();
         // FIXME: Emitting whitespace for this is really just a hack, we should get rid of it.
         // Add whitespace between adjoint puncts
-        let next = last.bump();
-        if let (
-            Some(tt::buffer::TokenTreeRef::Leaf(tt::Leaf::Punct(curr), _)),
-            Some(tt::buffer::TokenTreeRef::Leaf(tt::Leaf::Punct(next), _)),
-        ) = (last.token_tree(), next.token_tree())
-        {
+        if let Some([tt::Leaf::Punct(curr), tt::Leaf::Punct(next)]) = last_two {
             // Note: We always assume the semi-colon would be the last token in
             // other parts of RA such that we don't add whitespace here.
             //
@@ -1058,7 +999,7 @@ where
         // We don't do what rustc does exactly, rustc does something clever when the spans have different syntax contexts
         // but this runs afoul of our separation between `span` and `hir-expand`.
         SpanData {
-            range: if a.ctx == b.ctx {
+            range: if a.ctx == b.ctx && a.anchor == b.anchor {
                 TextRange::new(
                     std::cmp::min(a.range.start(), b.range.start()),
                     std::cmp::max(a.range.end(), b.range.end()),
diff --git a/src/tools/rust-analyzer/crates/syntax-bridge/src/tests.rs b/src/tools/rust-analyzer/crates/syntax-bridge/src/tests.rs
index 7b8e3f2b49c..d37cb508de1 100644
--- a/src/tools/rust-analyzer/crates/syntax-bridge/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/syntax-bridge/src/tests.rs
@@ -2,10 +2,7 @@ use rustc_hash::FxHashMap;
 use span::Span;
 use syntax::{ast, AstNode};
 use test_utils::extract_annotations;
-use tt::{
-    buffer::{TokenBuffer, TokenTreeRef},
-    Leaf, Punct, Spacing,
-};
+use tt::{buffer::Cursor, Leaf, Punct, Spacing};
 
 use crate::{
     dummy_test_span_utils::{DummyTestSpanMap, DUMMY},
@@ -32,22 +29,22 @@ fn check_punct_spacing(fixture: &str) {
         })
         .collect();
 
-    let buf = TokenBuffer::from_subtree(&subtree);
-    let mut cursor = buf.begin();
+    let mut cursor = Cursor::new(&subtree.0);
     while !cursor.eof() {
         while let Some(token_tree) = cursor.token_tree() {
-            if let TokenTreeRef::Leaf(
-                Leaf::Punct(Punct { spacing, span: Span { range, .. }, .. }),
-                _,
-            ) = token_tree
+            if let tt::TokenTree::Leaf(Leaf::Punct(Punct {
+                spacing,
+                span: Span { range, .. },
+                ..
+            })) = token_tree
             {
                 if let Some(expected) = annotations.remove(range) {
                     assert_eq!(expected, *spacing);
                 }
             }
-            cursor = cursor.bump_subtree();
+            cursor.bump();
         }
-        cursor = cursor.bump();
+        cursor.bump_or_end();
     }
 
     assert!(annotations.is_empty(), "unchecked annotations: {annotations:?}");
diff --git a/src/tools/rust-analyzer/crates/syntax-bridge/src/to_parser_input.rs b/src/tools/rust-analyzer/crates/syntax-bridge/src/to_parser_input.rs
index 14216e30932..1bbb05f5507 100644
--- a/src/tools/rust-analyzer/crates/syntax-bridge/src/to_parser_input.rs
+++ b/src/tools/rust-analyzer/crates/syntax-bridge/src/to_parser_input.rs
@@ -6,37 +6,34 @@ use std::fmt;
 use span::Edition;
 use syntax::{SyntaxKind, SyntaxKind::*, T};
 
-use tt::buffer::TokenBuffer;
-
 pub fn to_parser_input<S: Copy + fmt::Debug>(
     edition: Edition,
-    buffer: &TokenBuffer<'_, S>,
+    buffer: tt::TokenTreesView<'_, S>,
 ) -> parser::Input {
     let mut res = parser::Input::default();
 
-    let mut current = buffer.begin();
+    let mut current = buffer.cursor();
 
     while !current.eof() {
-        let cursor = current;
-        let tt = cursor.token_tree();
+        let tt = current.token_tree();
 
         // Check if it is lifetime
-        if let Some(tt::buffer::TokenTreeRef::Leaf(tt::Leaf::Punct(punct), _)) = tt {
+        if let Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) = tt {
             if punct.char == '\'' {
-                let next = cursor.bump();
-                match next.token_tree() {
-                    Some(tt::buffer::TokenTreeRef::Leaf(tt::Leaf::Ident(_ident), _)) => {
+                current.bump();
+                match current.token_tree() {
+                    Some(tt::TokenTree::Leaf(tt::Leaf::Ident(_ident))) => {
                         res.push(LIFETIME_IDENT);
-                        current = next.bump();
+                        current.bump();
                         continue;
                     }
-                    _ => panic!("Next token must be ident : {:#?}", next.token_tree()),
+                    _ => panic!("Next token must be ident"),
                 }
             }
         }
 
-        current = match tt {
-            Some(tt::buffer::TokenTreeRef::Leaf(leaf, _)) => {
+        match tt {
+            Some(tt::TokenTree::Leaf(leaf)) => {
                 match leaf {
                     tt::Leaf::Literal(lit) => {
                         let kind = match lit.kind {
@@ -83,9 +80,9 @@ pub fn to_parser_input<S: Copy + fmt::Debug>(
                         }
                     }
                 }
-                cursor.bump()
+                current.bump();
             }
-            Some(tt::buffer::TokenTreeRef::Subtree(subtree, _)) => {
+            Some(tt::TokenTree::Subtree(subtree)) => {
                 if let Some(kind) = match subtree.delimiter.kind {
                     tt::DelimiterKind::Parenthesis => Some(T!['(']),
                     tt::DelimiterKind::Brace => Some(T!['{']),
@@ -94,22 +91,19 @@ pub fn to_parser_input<S: Copy + fmt::Debug>(
                 } {
                     res.push(kind);
                 }
-                cursor.subtree().unwrap()
+                current.bump();
             }
-            None => match cursor.end() {
-                Some(subtree) => {
-                    if let Some(kind) = match subtree.delimiter.kind {
-                        tt::DelimiterKind::Parenthesis => Some(T![')']),
-                        tt::DelimiterKind::Brace => Some(T!['}']),
-                        tt::DelimiterKind::Bracket => Some(T![']']),
-                        tt::DelimiterKind::Invisible => None,
-                    } {
-                        res.push(kind);
-                    }
-                    cursor.bump()
+            None => {
+                let subtree = current.end();
+                if let Some(kind) = match subtree.delimiter.kind {
+                    tt::DelimiterKind::Parenthesis => Some(T![')']),
+                    tt::DelimiterKind::Brace => Some(T!['}']),
+                    tt::DelimiterKind::Bracket => Some(T![']']),
+                    tt::DelimiterKind::Invisible => None,
+                } {
+                    res.push(kind);
                 }
-                None => continue,
-            },
+            }
         };
     }
 
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast.rs b/src/tools/rust-analyzer/crates/syntax/src/ast.rs
index 32b1f5f7544..72a46f2f9f0 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast.rs
@@ -42,6 +42,14 @@ pub use self::{
 /// the same representation: a pointer to the tree root and a pointer to the
 /// node itself.
 pub trait AstNode {
+    /// This panics if the `SyntaxKind` is not statically known.
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        panic!("dynamic `SyntaxKind` for `AstNode::kind()`")
+    }
+
     fn can_cast(kind: SyntaxKind) -> bool
     where
         Self: Sized;
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs
index ffe9f16cfd5..291fc646e21 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/edit_in_place.rs
@@ -751,7 +751,7 @@ impl ast::MatchArmList {
         ted::insert_all(position, elements);
 
         fn needs_comma(arm: &ast::MatchArm) -> bool {
-            arm.expr().map_or(false, |e| !e.is_block_like()) && arm.comma_token().is_none()
+            arm.expr().is_some_and(|e| !e.is_block_like()) && arm.comma_token().is_none()
         }
     }
 }
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/expr_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/expr_ext.rs
index f3053f59836..9466755576b 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/expr_ext.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/expr_ext.rs
@@ -393,7 +393,7 @@ impl ast::BlockExpr {
             FOR_EXPR | IF_EXPR => parent
                 .children()
                 .find(|it| ast::Expr::can_cast(it.kind()))
-                .map_or(true, |it| it == *self.syntax()),
+                .is_none_or(|it| it == *self.syntax()),
             LET_ELSE | FN | WHILE_EXPR | LOOP_EXPR | CONST_BLOCK_PAT => false,
             _ => true,
         }
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 3876ef71a07..69e2a9f9c1b 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
@@ -2503,6 +2503,13 @@ pub struct AnyHasVisibility {
 impl ast::HasVisibility for AnyHasVisibility {}
 impl AstNode for Abi {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        ABI
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == ABI }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2517,6 +2524,13 @@ impl AstNode for Abi {
 }
 impl AstNode for ArgList {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        ARG_LIST
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == ARG_LIST }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2531,6 +2545,13 @@ impl AstNode for ArgList {
 }
 impl AstNode for ArrayExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        ARRAY_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == ARRAY_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2545,6 +2566,13 @@ impl AstNode for ArrayExpr {
 }
 impl AstNode for ArrayType {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        ARRAY_TYPE
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == ARRAY_TYPE }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2559,6 +2587,13 @@ impl AstNode for ArrayType {
 }
 impl AstNode for AsmClobberAbi {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        ASM_CLOBBER_ABI
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_CLOBBER_ABI }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2573,6 +2608,13 @@ impl AstNode for AsmClobberAbi {
 }
 impl AstNode for AsmConst {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        ASM_CONST
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_CONST }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2587,6 +2629,13 @@ impl AstNode for AsmConst {
 }
 impl AstNode for AsmDirSpec {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        ASM_DIR_SPEC
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_DIR_SPEC }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2601,6 +2650,13 @@ impl AstNode for AsmDirSpec {
 }
 impl AstNode for AsmExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        ASM_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2615,6 +2671,13 @@ impl AstNode for AsmExpr {
 }
 impl AstNode for AsmLabel {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        ASM_LABEL
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_LABEL }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2629,6 +2692,13 @@ impl AstNode for AsmLabel {
 }
 impl AstNode for AsmOperandExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        ASM_OPERAND_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_OPERAND_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2643,6 +2713,13 @@ impl AstNode for AsmOperandExpr {
 }
 impl AstNode for AsmOperandNamed {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        ASM_OPERAND_NAMED
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_OPERAND_NAMED }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2657,6 +2734,13 @@ impl AstNode for AsmOperandNamed {
 }
 impl AstNode for AsmOption {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        ASM_OPTION
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_OPTION }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2671,6 +2755,13 @@ impl AstNode for AsmOption {
 }
 impl AstNode for AsmOptions {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        ASM_OPTIONS
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_OPTIONS }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2685,6 +2776,13 @@ impl AstNode for AsmOptions {
 }
 impl AstNode for AsmRegOperand {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        ASM_REG_OPERAND
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_REG_OPERAND }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2699,6 +2797,13 @@ impl AstNode for AsmRegOperand {
 }
 impl AstNode for AsmRegSpec {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        ASM_REG_SPEC
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_REG_SPEC }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2713,6 +2818,13 @@ impl AstNode for AsmRegSpec {
 }
 impl AstNode for AsmSym {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        ASM_SYM
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == ASM_SYM }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2727,6 +2839,13 @@ impl AstNode for AsmSym {
 }
 impl AstNode for AssocItemList {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        ASSOC_ITEM_LIST
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == ASSOC_ITEM_LIST }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2741,6 +2860,13 @@ impl AstNode for AssocItemList {
 }
 impl AstNode for AssocTypeArg {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        ASSOC_TYPE_ARG
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == ASSOC_TYPE_ARG }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2755,6 +2881,13 @@ impl AstNode for AssocTypeArg {
 }
 impl AstNode for Attr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        ATTR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == ATTR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2769,6 +2902,13 @@ impl AstNode for Attr {
 }
 impl AstNode for AwaitExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        AWAIT_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == AWAIT_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2783,6 +2923,13 @@ impl AstNode for AwaitExpr {
 }
 impl AstNode for BecomeExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        BECOME_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == BECOME_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2797,6 +2944,13 @@ impl AstNode for BecomeExpr {
 }
 impl AstNode for BinExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        BIN_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == BIN_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2811,6 +2965,13 @@ impl AstNode for BinExpr {
 }
 impl AstNode for BlockExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        BLOCK_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == BLOCK_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2825,6 +2986,13 @@ impl AstNode for BlockExpr {
 }
 impl AstNode for BoxPat {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        BOX_PAT
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == BOX_PAT }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2839,6 +3007,13 @@ impl AstNode for BoxPat {
 }
 impl AstNode for BreakExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        BREAK_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == BREAK_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2853,6 +3028,13 @@ impl AstNode for BreakExpr {
 }
 impl AstNode for CallExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        CALL_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == CALL_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2867,6 +3049,13 @@ impl AstNode for CallExpr {
 }
 impl AstNode for CastExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        CAST_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == CAST_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2881,6 +3070,13 @@ impl AstNode for CastExpr {
 }
 impl AstNode for ClosureBinder {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        CLOSURE_BINDER
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == CLOSURE_BINDER }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2895,6 +3091,13 @@ impl AstNode for ClosureBinder {
 }
 impl AstNode for ClosureExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        CLOSURE_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == CLOSURE_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2909,6 +3112,13 @@ impl AstNode for ClosureExpr {
 }
 impl AstNode for Const {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        CONST
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == CONST }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2923,6 +3133,13 @@ impl AstNode for Const {
 }
 impl AstNode for ConstArg {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        CONST_ARG
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_ARG }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2937,6 +3154,13 @@ impl AstNode for ConstArg {
 }
 impl AstNode for ConstBlockPat {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        CONST_BLOCK_PAT
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_BLOCK_PAT }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2951,6 +3175,13 @@ impl AstNode for ConstBlockPat {
 }
 impl AstNode for ConstParam {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        CONST_PARAM
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_PARAM }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2965,6 +3196,13 @@ impl AstNode for ConstParam {
 }
 impl AstNode for ContinueExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        CONTINUE_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == CONTINUE_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2979,6 +3217,13 @@ impl AstNode for ContinueExpr {
 }
 impl AstNode for DynTraitType {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        DYN_TRAIT_TYPE
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == DYN_TRAIT_TYPE }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -2993,6 +3238,13 @@ impl AstNode for DynTraitType {
 }
 impl AstNode for Enum {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        ENUM
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == ENUM }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3007,6 +3259,13 @@ impl AstNode for Enum {
 }
 impl AstNode for ExprStmt {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        EXPR_STMT
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_STMT }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3021,6 +3280,13 @@ impl AstNode for ExprStmt {
 }
 impl AstNode for ExternBlock {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        EXTERN_BLOCK
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_BLOCK }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3035,6 +3301,13 @@ impl AstNode for ExternBlock {
 }
 impl AstNode for ExternCrate {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        EXTERN_CRATE
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_CRATE }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3049,6 +3322,13 @@ impl AstNode for ExternCrate {
 }
 impl AstNode for ExternItemList {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        EXTERN_ITEM_LIST
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_ITEM_LIST }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3063,6 +3343,13 @@ impl AstNode for ExternItemList {
 }
 impl AstNode for FieldExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        FIELD_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == FIELD_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3077,6 +3364,13 @@ impl AstNode for FieldExpr {
 }
 impl AstNode for Fn {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        FN
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == FN }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3091,6 +3385,13 @@ impl AstNode for Fn {
 }
 impl AstNode for FnPtrType {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        FN_PTR_TYPE
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == FN_PTR_TYPE }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3105,6 +3406,13 @@ impl AstNode for FnPtrType {
 }
 impl AstNode for ForExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        FOR_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3119,6 +3427,13 @@ impl AstNode for ForExpr {
 }
 impl AstNode for ForType {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        FOR_TYPE
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_TYPE }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3133,6 +3448,13 @@ impl AstNode for ForType {
 }
 impl AstNode for FormatArgsArg {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        FORMAT_ARGS_ARG
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == FORMAT_ARGS_ARG }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3147,6 +3469,13 @@ impl AstNode for FormatArgsArg {
 }
 impl AstNode for FormatArgsExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        FORMAT_ARGS_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == FORMAT_ARGS_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3161,6 +3490,13 @@ impl AstNode for FormatArgsExpr {
 }
 impl AstNode for GenericArgList {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        GENERIC_ARG_LIST
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == GENERIC_ARG_LIST }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3175,6 +3511,13 @@ impl AstNode for GenericArgList {
 }
 impl AstNode for GenericParamList {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        GENERIC_PARAM_LIST
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == GENERIC_PARAM_LIST }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3189,6 +3532,13 @@ impl AstNode for GenericParamList {
 }
 impl AstNode for IdentPat {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        IDENT_PAT
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == IDENT_PAT }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3203,6 +3553,13 @@ impl AstNode for IdentPat {
 }
 impl AstNode for IfExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        IF_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == IF_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3217,6 +3574,13 @@ impl AstNode for IfExpr {
 }
 impl AstNode for Impl {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        IMPL
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == IMPL }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3231,6 +3595,13 @@ impl AstNode for Impl {
 }
 impl AstNode for ImplTraitType {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        IMPL_TRAIT_TYPE
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == IMPL_TRAIT_TYPE }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3245,6 +3616,13 @@ impl AstNode for ImplTraitType {
 }
 impl AstNode for IndexExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        INDEX_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == INDEX_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3259,6 +3637,13 @@ impl AstNode for IndexExpr {
 }
 impl AstNode for InferType {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        INFER_TYPE
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == INFER_TYPE }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3273,6 +3658,13 @@ impl AstNode for InferType {
 }
 impl AstNode for ItemList {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        ITEM_LIST
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == ITEM_LIST }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3287,6 +3679,13 @@ impl AstNode for ItemList {
 }
 impl AstNode for Label {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        LABEL
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == LABEL }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3301,6 +3700,13 @@ impl AstNode for Label {
 }
 impl AstNode for LetElse {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        LET_ELSE
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == LET_ELSE }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3315,6 +3721,13 @@ impl AstNode for LetElse {
 }
 impl AstNode for LetExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        LET_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == LET_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3329,6 +3742,13 @@ impl AstNode for LetExpr {
 }
 impl AstNode for LetStmt {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        LET_STMT
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == LET_STMT }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3343,6 +3763,13 @@ impl AstNode for LetStmt {
 }
 impl AstNode for Lifetime {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        LIFETIME
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == LIFETIME }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3357,6 +3784,13 @@ impl AstNode for Lifetime {
 }
 impl AstNode for LifetimeArg {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        LIFETIME_ARG
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == LIFETIME_ARG }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3371,6 +3805,13 @@ impl AstNode for LifetimeArg {
 }
 impl AstNode for LifetimeParam {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        LIFETIME_PARAM
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == LIFETIME_PARAM }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3385,6 +3826,13 @@ impl AstNode for LifetimeParam {
 }
 impl AstNode for Literal {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        LITERAL
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == LITERAL }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3399,6 +3847,13 @@ impl AstNode for Literal {
 }
 impl AstNode for LiteralPat {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        LITERAL_PAT
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == LITERAL_PAT }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3413,6 +3868,13 @@ impl AstNode for LiteralPat {
 }
 impl AstNode for LoopExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        LOOP_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == LOOP_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3427,6 +3889,13 @@ impl AstNode for LoopExpr {
 }
 impl AstNode for MacroCall {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        MACRO_CALL
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_CALL }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3441,6 +3910,13 @@ impl AstNode for MacroCall {
 }
 impl AstNode for MacroDef {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        MACRO_DEF
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_DEF }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3455,6 +3931,13 @@ impl AstNode for MacroDef {
 }
 impl AstNode for MacroExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        MACRO_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3469,6 +3952,13 @@ impl AstNode for MacroExpr {
 }
 impl AstNode for MacroItems {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        MACRO_ITEMS
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_ITEMS }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3483,6 +3973,13 @@ impl AstNode for MacroItems {
 }
 impl AstNode for MacroPat {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        MACRO_PAT
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_PAT }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3497,6 +3994,13 @@ impl AstNode for MacroPat {
 }
 impl AstNode for MacroRules {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        MACRO_RULES
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_RULES }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3511,6 +4015,13 @@ impl AstNode for MacroRules {
 }
 impl AstNode for MacroStmts {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        MACRO_STMTS
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_STMTS }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3525,6 +4036,13 @@ impl AstNode for MacroStmts {
 }
 impl AstNode for MacroType {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        MACRO_TYPE
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_TYPE }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3539,6 +4057,13 @@ impl AstNode for MacroType {
 }
 impl AstNode for MatchArm {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        MATCH_ARM
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_ARM }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3553,6 +4078,13 @@ impl AstNode for MatchArm {
 }
 impl AstNode for MatchArmList {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        MATCH_ARM_LIST
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_ARM_LIST }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3567,6 +4099,13 @@ impl AstNode for MatchArmList {
 }
 impl AstNode for MatchExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        MATCH_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3581,6 +4120,13 @@ impl AstNode for MatchExpr {
 }
 impl AstNode for MatchGuard {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        MATCH_GUARD
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_GUARD }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3595,6 +4141,13 @@ impl AstNode for MatchGuard {
 }
 impl AstNode for Meta {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        META
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == META }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3609,6 +4162,13 @@ impl AstNode for Meta {
 }
 impl AstNode for MethodCallExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        METHOD_CALL_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == METHOD_CALL_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3623,6 +4183,13 @@ impl AstNode for MethodCallExpr {
 }
 impl AstNode for Module {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        MODULE
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == MODULE }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3637,6 +4204,13 @@ impl AstNode for Module {
 }
 impl AstNode for Name {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        NAME
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == NAME }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3651,6 +4225,13 @@ impl AstNode for Name {
 }
 impl AstNode for NameRef {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        NAME_REF
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == NAME_REF }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3665,6 +4246,13 @@ impl AstNode for NameRef {
 }
 impl AstNode for NeverType {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        NEVER_TYPE
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == NEVER_TYPE }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3679,6 +4267,13 @@ impl AstNode for NeverType {
 }
 impl AstNode for OffsetOfExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        OFFSET_OF_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == OFFSET_OF_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3693,6 +4288,13 @@ impl AstNode for OffsetOfExpr {
 }
 impl AstNode for OrPat {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        OR_PAT
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == OR_PAT }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3707,6 +4309,13 @@ impl AstNode for OrPat {
 }
 impl AstNode for Param {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        PARAM
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3721,6 +4330,13 @@ impl AstNode for Param {
 }
 impl AstNode for ParamList {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        PARAM_LIST
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM_LIST }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3735,6 +4351,13 @@ impl AstNode for ParamList {
 }
 impl AstNode for ParenExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        PAREN_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3749,6 +4372,13 @@ impl AstNode for ParenExpr {
 }
 impl AstNode for ParenPat {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        PAREN_PAT
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_PAT }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3763,6 +4393,13 @@ impl AstNode for ParenPat {
 }
 impl AstNode for ParenType {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        PAREN_TYPE
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_TYPE }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3777,6 +4414,13 @@ impl AstNode for ParenType {
 }
 impl AstNode for ParenthesizedArgList {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        PARENTHESIZED_ARG_LIST
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == PARENTHESIZED_ARG_LIST }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3791,6 +4435,13 @@ impl AstNode for ParenthesizedArgList {
 }
 impl AstNode for Path {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        PATH
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == PATH }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3805,6 +4456,13 @@ impl AstNode for Path {
 }
 impl AstNode for PathExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        PATH_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3819,6 +4477,13 @@ impl AstNode for PathExpr {
 }
 impl AstNode for PathPat {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        PATH_PAT
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_PAT }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3833,6 +4498,13 @@ impl AstNode for PathPat {
 }
 impl AstNode for PathSegment {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        PATH_SEGMENT
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_SEGMENT }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3847,6 +4519,13 @@ impl AstNode for PathSegment {
 }
 impl AstNode for PathType {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        PATH_TYPE
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_TYPE }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3861,6 +4540,13 @@ impl AstNode for PathType {
 }
 impl AstNode for PrefixExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        PREFIX_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == PREFIX_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3875,6 +4561,13 @@ impl AstNode for PrefixExpr {
 }
 impl AstNode for PtrType {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        PTR_TYPE
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == PTR_TYPE }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3889,6 +4582,13 @@ impl AstNode for PtrType {
 }
 impl AstNode for RangeExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        RANGE_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == RANGE_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3903,6 +4603,13 @@ impl AstNode for RangeExpr {
 }
 impl AstNode for RangePat {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        RANGE_PAT
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == RANGE_PAT }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3917,6 +4624,13 @@ impl AstNode for RangePat {
 }
 impl AstNode for RecordExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        RECORD_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3931,6 +4645,13 @@ impl AstNode for RecordExpr {
 }
 impl AstNode for RecordExprField {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        RECORD_EXPR_FIELD
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_EXPR_FIELD }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3945,6 +4666,13 @@ impl AstNode for RecordExprField {
 }
 impl AstNode for RecordExprFieldList {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        RECORD_EXPR_FIELD_LIST
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_EXPR_FIELD_LIST }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3959,6 +4687,13 @@ impl AstNode for RecordExprFieldList {
 }
 impl AstNode for RecordField {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        RECORD_FIELD
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3973,6 +4708,13 @@ impl AstNode for RecordField {
 }
 impl AstNode for RecordFieldList {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        RECORD_FIELD_LIST
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD_LIST }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -3987,6 +4729,13 @@ impl AstNode for RecordFieldList {
 }
 impl AstNode for RecordPat {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        RECORD_PAT
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4001,6 +4750,13 @@ impl AstNode for RecordPat {
 }
 impl AstNode for RecordPatField {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        RECORD_PAT_FIELD
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT_FIELD }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4015,6 +4771,13 @@ impl AstNode for RecordPatField {
 }
 impl AstNode for RecordPatFieldList {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        RECORD_PAT_FIELD_LIST
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT_FIELD_LIST }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4029,6 +4792,13 @@ impl AstNode for RecordPatFieldList {
 }
 impl AstNode for RefExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        REF_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == REF_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4043,6 +4813,13 @@ impl AstNode for RefExpr {
 }
 impl AstNode for RefPat {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        REF_PAT
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == REF_PAT }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4057,6 +4834,13 @@ impl AstNode for RefPat {
 }
 impl AstNode for RefType {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        REF_TYPE
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == REF_TYPE }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4071,6 +4855,13 @@ impl AstNode for RefType {
 }
 impl AstNode for Rename {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        RENAME
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == RENAME }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4085,6 +4876,13 @@ impl AstNode for Rename {
 }
 impl AstNode for RestPat {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        REST_PAT
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == REST_PAT }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4099,6 +4897,13 @@ impl AstNode for RestPat {
 }
 impl AstNode for RetType {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        RET_TYPE
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == RET_TYPE }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4113,6 +4918,13 @@ impl AstNode for RetType {
 }
 impl AstNode for ReturnExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        RETURN_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == RETURN_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4127,6 +4939,13 @@ impl AstNode for ReturnExpr {
 }
 impl AstNode for ReturnTypeSyntax {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        RETURN_TYPE_SYNTAX
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == RETURN_TYPE_SYNTAX }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4141,6 +4960,13 @@ impl AstNode for ReturnTypeSyntax {
 }
 impl AstNode for SelfParam {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        SELF_PARAM
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == SELF_PARAM }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4155,6 +4981,13 @@ impl AstNode for SelfParam {
 }
 impl AstNode for SlicePat {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        SLICE_PAT
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == SLICE_PAT }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4169,6 +5002,13 @@ impl AstNode for SlicePat {
 }
 impl AstNode for SliceType {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        SLICE_TYPE
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == SLICE_TYPE }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4183,6 +5023,13 @@ impl AstNode for SliceType {
 }
 impl AstNode for SourceFile {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        SOURCE_FILE
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == SOURCE_FILE }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4197,6 +5044,13 @@ impl AstNode for SourceFile {
 }
 impl AstNode for Static {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        STATIC
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == STATIC }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4211,6 +5065,13 @@ impl AstNode for Static {
 }
 impl AstNode for StmtList {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        STMT_LIST
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == STMT_LIST }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4225,6 +5086,13 @@ impl AstNode for StmtList {
 }
 impl AstNode for Struct {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        STRUCT
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == STRUCT }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4239,6 +5107,13 @@ impl AstNode for Struct {
 }
 impl AstNode for TokenTree {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        TOKEN_TREE
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == TOKEN_TREE }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4253,6 +5128,13 @@ impl AstNode for TokenTree {
 }
 impl AstNode for Trait {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        TRAIT
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == TRAIT }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4267,6 +5149,13 @@ impl AstNode for Trait {
 }
 impl AstNode for TraitAlias {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        TRAIT_ALIAS
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == TRAIT_ALIAS }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4281,6 +5170,13 @@ impl AstNode for TraitAlias {
 }
 impl AstNode for TryExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        TRY_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == TRY_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4295,6 +5191,13 @@ impl AstNode for TryExpr {
 }
 impl AstNode for TupleExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        TUPLE_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4309,6 +5212,13 @@ impl AstNode for TupleExpr {
 }
 impl AstNode for TupleField {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        TUPLE_FIELD
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_FIELD }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4323,6 +5233,13 @@ impl AstNode for TupleField {
 }
 impl AstNode for TupleFieldList {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        TUPLE_FIELD_LIST
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_FIELD_LIST }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4337,6 +5254,13 @@ impl AstNode for TupleFieldList {
 }
 impl AstNode for TuplePat {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        TUPLE_PAT
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_PAT }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4351,6 +5275,13 @@ impl AstNode for TuplePat {
 }
 impl AstNode for TupleStructPat {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        TUPLE_STRUCT_PAT
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_STRUCT_PAT }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4365,6 +5296,13 @@ impl AstNode for TupleStructPat {
 }
 impl AstNode for TupleType {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        TUPLE_TYPE
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_TYPE }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4379,6 +5317,13 @@ impl AstNode for TupleType {
 }
 impl AstNode for TypeAlias {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        TYPE_ALIAS
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_ALIAS }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4393,6 +5338,13 @@ impl AstNode for TypeAlias {
 }
 impl AstNode for TypeArg {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        TYPE_ARG
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_ARG }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4407,6 +5359,13 @@ impl AstNode for TypeArg {
 }
 impl AstNode for TypeBound {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        TYPE_BOUND
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_BOUND }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4421,6 +5380,13 @@ impl AstNode for TypeBound {
 }
 impl AstNode for TypeBoundList {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        TYPE_BOUND_LIST
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_BOUND_LIST }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4435,6 +5401,13 @@ impl AstNode for TypeBoundList {
 }
 impl AstNode for TypeParam {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        TYPE_PARAM
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_PARAM }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4449,6 +5422,13 @@ impl AstNode for TypeParam {
 }
 impl AstNode for UnderscoreExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        UNDERSCORE_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == UNDERSCORE_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4463,6 +5443,13 @@ impl AstNode for UnderscoreExpr {
 }
 impl AstNode for Union {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        UNION
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == UNION }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4477,6 +5464,13 @@ impl AstNode for Union {
 }
 impl AstNode for Use {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        USE
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == USE }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4491,6 +5485,13 @@ impl AstNode for Use {
 }
 impl AstNode for UseBoundGenericArgs {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        USE_BOUND_GENERIC_ARGS
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == USE_BOUND_GENERIC_ARGS }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4505,6 +5506,13 @@ impl AstNode for UseBoundGenericArgs {
 }
 impl AstNode for UseTree {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        USE_TREE
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4519,6 +5527,13 @@ impl AstNode for UseTree {
 }
 impl AstNode for UseTreeList {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        USE_TREE_LIST
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE_LIST }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4533,6 +5548,13 @@ impl AstNode for UseTreeList {
 }
 impl AstNode for Variant {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        VARIANT
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == VARIANT }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4547,6 +5569,13 @@ impl AstNode for Variant {
 }
 impl AstNode for VariantList {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        VARIANT_LIST
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == VARIANT_LIST }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4561,6 +5590,13 @@ impl AstNode for VariantList {
 }
 impl AstNode for Visibility {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        VISIBILITY
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == VISIBILITY }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4575,6 +5611,13 @@ impl AstNode for Visibility {
 }
 impl AstNode for WhereClause {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        WHERE_CLAUSE
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == WHERE_CLAUSE }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4589,6 +5632,13 @@ impl AstNode for WhereClause {
 }
 impl AstNode for WherePred {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        WHERE_PRED
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == WHERE_PRED }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4603,6 +5653,13 @@ impl AstNode for WherePred {
 }
 impl AstNode for WhileExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        WHILE_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == WHILE_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4617,6 +5674,13 @@ impl AstNode for WhileExpr {
 }
 impl AstNode for WildcardPat {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        WILDCARD_PAT
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == WILDCARD_PAT }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4631,6 +5695,13 @@ impl AstNode for WildcardPat {
 }
 impl AstNode for YeetExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        YEET_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == YEET_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
@@ -4645,6 +5716,13 @@ impl AstNode for YeetExpr {
 }
 impl AstNode for YieldExpr {
     #[inline]
+    fn kind() -> SyntaxKind
+    where
+        Self: Sized,
+    {
+        YIELD_EXPR
+    }
+    #[inline]
     fn can_cast(kind: SyntaxKind) -> bool { kind == YIELD_EXPR }
     #[inline]
     fn cast(syntax: SyntaxNode) -> Option<Self> {
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
index eb96ab6ef59..282cbc4b3a4 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
@@ -8,7 +8,10 @@
 //! Keep in mind that `from_text` functions should be kept private. The public
 //! API should require to assemble every node piecewise. The trick of
 //! `parse(format!())` we use internally is an implementation detail -- long
-//! term, it will be replaced with direct tree manipulation.
+//! term, it will be replaced with `quote!`. Do not add more usages to `from_text` -
+//! use `quote!` instead.
+
+mod quote;
 
 use itertools::Itertools;
 use parser::{Edition, T};
@@ -16,7 +19,7 @@ use rowan::NodeOrToken;
 use stdx::{format_to, format_to_acc, never};
 
 use crate::{
-    ast::{self, Param},
+    ast::{self, make::quote::quote, Param},
     utils::is_raw_identifier,
     AstNode, SourceFile, SyntaxKind, SyntaxToken,
 };
@@ -118,7 +121,11 @@ pub fn name(name: &str) -> ast::Name {
 }
 pub fn name_ref(name_ref: &str) -> ast::NameRef {
     let raw_escape = raw_ident_esc(name_ref);
-    ast_from_text(&format!("fn f() {{ {raw_escape}{name_ref}; }}"))
+    quote! {
+        NameRef {
+            [IDENT format!("{raw_escape}{name_ref}")]
+        }
+    }
 }
 fn raw_ident_esc(ident: &str) -> &'static str {
     if is_raw_identifier(ident, Edition::CURRENT) {
@@ -135,7 +142,11 @@ pub fn lifetime(text: &str) -> ast::Lifetime {
         tmp = format!("'{text}");
         text = &tmp;
     }
-    ast_from_text(&format!("fn f<{text}>() {{ }}"))
+    quote! {
+        Lifetime {
+            [LIFETIME_IDENT text]
+        }
+    }
 }
 
 // FIXME: replace stringly-typed constructor with a family of typed ctors, a-la
@@ -175,63 +186,37 @@ pub fn ty_alias(
     where_clause: Option<ast::WhereClause>,
     assignment: Option<(ast::Type, Option<ast::WhereClause>)>,
 ) -> ast::TypeAlias {
-    let mut s = String::new();
-    s.push_str(&format!("type {ident}"));
-
-    if let Some(list) = generic_param_list {
-        s.push_str(&list.to_string());
-    }
-
-    if let Some(list) = type_param_bounds {
-        s.push_str(&format!(" : {list}"));
-    }
-
-    if let Some(cl) = where_clause {
-        s.push_str(&format!(" {cl}"));
-    }
-
-    if let Some(exp) = assignment {
-        if let Some(cl) = exp.1 {
-            s.push_str(&format!(" = {} {cl}", exp.0));
-        } else {
-            s.push_str(&format!(" = {}", exp.0));
+    let (assignment_ty, assignment_where) = assignment.unzip();
+    let assignment_where = assignment_where.flatten();
+    quote! {
+        TypeAlias {
+            [type] " "
+                Name { [IDENT ident] }
+                #generic_param_list
+                #(" " [:] " " #type_param_bounds)*
+                #(" " #where_clause)*
+                #(" " [=] " " #assignment_ty)*
+                #(" " #assignment_where)*
+            [;]
         }
     }
-
-    s.push(';');
-    ast_from_text(&s)
 }
 
 pub fn ty_fn_ptr<I: Iterator<Item = Param>>(
-    for_lifetime_list: Option<ast::GenericParamList>,
     is_unsafe: bool,
     abi: Option<ast::Abi>,
-    params: I,
+    mut params: I,
     ret_type: Option<ast::RetType>,
 ) -> ast::FnPtrType {
-    let mut s = String::from("type __ = ");
-
-    if let Some(list) = for_lifetime_list {
-        format_to!(s, "for{} ", list);
-    }
-
-    if is_unsafe {
-        s.push_str("unsafe ");
-    }
-
-    if let Some(abi) = abi {
-        format_to!(s, "{} ", abi)
-    }
-
-    s.push_str("fn");
-
-    format_to!(s, "({})", params.map(|p| p.to_string()).join(", "));
-
-    if let Some(ret_type) = ret_type {
-        format_to!(s, " {}", ret_type);
+    let is_unsafe = is_unsafe.then_some(());
+    let first_param = params.next();
+    quote! {
+        FnPtrType {
+            #(#is_unsafe [unsafe] " ")* #(#abi " ")* [fn]
+                ['('] #first_param #([,] " " #params)* [')']
+                #(" " #ret_type)*
+        }
     }
-
-    ast_from_text(&s)
 }
 
 pub fn assoc_item_list() -> ast::AssocItemList {
@@ -351,6 +336,24 @@ pub fn path_segment(name_ref: ast::NameRef) -> ast::PathSegment {
     ast_from_text(&format!("type __ = {name_ref};"))
 }
 
+/// Type and expressions/patterns path differ in whether they require `::` before generic arguments.
+/// Type paths allow them but they are often omitted, while expression/pattern paths require them.
+pub fn generic_ty_path_segment(
+    name_ref: ast::NameRef,
+    generic_args: impl IntoIterator<Item = ast::GenericArg>,
+) -> ast::PathSegment {
+    let mut generic_args = generic_args.into_iter();
+    let first_generic_arg = generic_args.next();
+    quote! {
+        PathSegment {
+            #name_ref
+            GenericArgList {
+                [<] #first_generic_arg #([,] " " #generic_args)* [>]
+            }
+        }
+    }
+}
+
 pub fn path_segment_ty(type_ref: ast::Type, trait_ref: Option<ast::PathType>) -> ast::PathSegment {
     let text = match trait_ref {
         Some(trait_ref) => format!("fn f(x: <{type_ref} as {trait_ref}>) {{}}"),
@@ -480,15 +483,16 @@ pub fn block_expr(
     stmts: impl IntoIterator<Item = ast::Stmt>,
     tail_expr: Option<ast::Expr>,
 ) -> ast::BlockExpr {
-    let mut buf = "{\n".to_owned();
-    for stmt in stmts.into_iter() {
-        format_to!(buf, "    {stmt}\n");
-    }
-    if let Some(tail_expr) = tail_expr {
-        format_to!(buf, "    {tail_expr}\n");
+    quote! {
+        BlockExpr {
+            StmtList {
+                ['{'] "\n"
+                #("    " #stmts "\n")*
+                #("    " #tail_expr "\n")*
+                ['}']
+            }
+        }
     }
-    buf += "}";
-    ast_from_text(&format!("fn f() {buf}"))
 }
 
 pub fn async_move_block_expr(
@@ -815,7 +819,7 @@ pub fn match_arm_with_guard(
 
 pub fn match_arm_list(arms: impl IntoIterator<Item = ast::MatchArm>) -> ast::MatchArmList {
     let arms_str = arms.into_iter().fold(String::new(), |mut acc, arm| {
-        let needs_comma = arm.expr().map_or(true, |it| !it.is_block_like());
+        let needs_comma = arm.expr().is_none_or(|it| !it.is_block_like());
         let comma = if needs_comma { "," } else { "" };
         let arm = arm.syntax();
         format_to_acc!(acc, "    {arm}{comma}\n")
@@ -828,7 +832,7 @@ pub fn match_arm_list(arms: impl IntoIterator<Item = ast::MatchArm>) -> ast::Mat
 }
 
 pub fn where_pred(
-    path: ast::Path,
+    path: ast::Type,
     bounds: impl IntoIterator<Item = ast::TypeBound>,
 ) -> ast::WherePred {
     let bounds = bounds.into_iter().join(" + ");
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/make/quote.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/make/quote.rs
new file mode 100644
index 00000000000..300ef25c137
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make/quote.rs
@@ -0,0 +1,191 @@
+//! A `quote!`-like API for crafting AST nodes.
+
+pub(crate) use rowan::{GreenNode, GreenToken, NodeOrToken, SyntaxKind as RSyntaxKind};
+
+macro_rules! quote_impl_ {
+    ( @append $children:ident ) => {}; // Base case.
+
+    ( @append $children:ident
+        $node:ident {
+            $($tree:tt)*
+        }
+        $($rest:tt)*
+    ) => {
+        {
+            #[allow(unused_mut)]
+            let mut inner_children = ::std::vec::Vec::<$crate::ast::make::quote::NodeOrToken<
+                $crate::ast::make::quote::GreenNode,
+                $crate::ast::make::quote::GreenToken,
+            >>::new();
+            $crate::ast::make::quote::quote_impl!( @append inner_children
+                $($tree)*
+            );
+            let kind = <$crate::ast::$node as $crate::ast::AstNode>::kind();
+            let node = $crate::ast::make::quote::GreenNode::new($crate::ast::make::quote::RSyntaxKind(kind as u16), inner_children);
+            $children.push($crate::ast::make::quote::NodeOrToken::Node(node));
+        }
+        $crate::ast::make::quote::quote_impl!( @append $children $($rest)* );
+    };
+
+    ( @append $children:ident
+        [ $token_kind:ident $token_text:expr ]
+        $($rest:tt)*
+    ) => {
+        $children.push($crate::ast::make::quote::NodeOrToken::Token(
+            $crate::ast::make::quote::GreenToken::new(
+                $crate::ast::make::quote::RSyntaxKind($crate::SyntaxKind::$token_kind as u16),
+                &$token_text,
+            ),
+        ));
+        $crate::ast::make::quote::quote_impl!( @append $children $($rest)* );
+    };
+
+    ( @append $children:ident
+        [$($token:tt)+]
+        $($rest:tt)*
+    ) => {
+        $children.push($crate::ast::make::quote::NodeOrToken::Token(
+            $crate::ast::make::quote::GreenToken::new(
+                $crate::ast::make::quote::RSyntaxKind($crate::T![ $($token)+ ] as u16),
+                const { $crate::T![ $($token)+ ].text() },
+            ),
+        ));
+        $crate::ast::make::quote::quote_impl!( @append $children $($rest)* );
+    };
+
+    ( @append $children:ident
+        $whitespace:literal
+        $($rest:tt)*
+    ) => {
+        const { $crate::ast::make::quote::verify_only_whitespaces($whitespace) };
+        $children.push($crate::ast::make::quote::NodeOrToken::Token(
+            $crate::ast::make::quote::GreenToken::new(
+                $crate::ast::make::quote::RSyntaxKind($crate::SyntaxKind::WHITESPACE as u16),
+                $whitespace,
+            ),
+        ));
+        $crate::ast::make::quote::quote_impl!( @append $children $($rest)* );
+    };
+
+    ( @append $children:ident
+        # $var:ident
+        $($rest:tt)*
+    ) => {
+        $crate::ast::make::quote::ToNodeChild::append_node_child($var, &mut $children);
+        $crate::ast::make::quote::quote_impl!( @append $children $($rest)* );
+    };
+
+    ( @append $children:ident
+        #( $($repetition:tt)+ )*
+        $($rest:tt)*
+    ) => {
+        $crate::ast::make::quote::quote_impl!( @extract_pounded_in_repetition $children
+            [] [] $($repetition)*
+        );
+        $crate::ast::make::quote::quote_impl!( @append $children $($rest)* );
+    };
+
+    // Base case - no repetition var.
+    ( @extract_pounded_in_repetition $children:ident
+        [ $($repetition:tt)* ] [ ]
+    ) => {
+        ::std::compile_error!("repetition in `ast::make::quote!()` without variable");
+    };
+
+    // Base case - repetition var found.
+    ( @extract_pounded_in_repetition $children:ident
+        [ $($repetition:tt)* ] [ $repetition_var:ident ]
+    ) => {
+        ::std::iter::IntoIterator::into_iter($repetition_var).for_each(|$repetition_var| {
+            $crate::ast::make::quote::quote_impl!( @append $children $($repetition)* );
+        });
+    };
+
+    ( @extract_pounded_in_repetition $children:ident
+        [ $($repetition:tt)* ] [ $repetition_var1:ident ] # $repetition_var2:ident $($rest:tt)*
+    ) => {
+        ::std::compile_error!("repetition in `ast::make::quote!()` with more than one variable");
+    };
+
+    ( @extract_pounded_in_repetition $children:ident
+        [ $($repetition:tt)* ] [ ] # $repetition_var:ident $($rest:tt)*
+    ) => {
+        $crate::ast::make::quote::quote_impl!( @extract_pounded_in_repetition $children
+            [ $($repetition)* # $repetition_var ] [ $repetition_var ] $($rest)*
+        );
+    };
+
+    ( @extract_pounded_in_repetition $children:ident
+        [ $($repetition:tt)* ] [ $($repetition_var:tt)* ] $non_repetition_var:tt $($rest:tt)*
+    ) => {
+        $crate::ast::make::quote::quote_impl!( @extract_pounded_in_repetition $children
+            [ $($repetition)* $non_repetition_var ] [ $($repetition_var)* ] $($rest)*
+        );
+    };
+}
+pub(crate) use quote_impl_ as quote_impl;
+
+/// A `quote!`-like API for crafting AST nodes.
+///
+/// Syntax: AST nodes are created with `Node { children }`, where `Node` is the node name in `ast` (`ast::Node`).
+/// Tokens are creates with their syntax enclosed by brackets, e.g. `[::]` or `['{']`. Alternatively, tokens can
+/// be created with the syntax `[token_kind token_text]`, where `token_kind` is a variant of `SyntaxKind` (e.g.
+/// `IDENT`) and `token_text` is an expression producing `String` or `&str`. Whitespaces can be added
+/// as string literals (i.e. `"\n    "` is a whitespace token). Interpolation is allowed with `#` (`#variable`),
+/// from `AstNode`s and `Option`s of them. Repetition is also supported, with only one repeating variable
+/// and no separator (`#("\n" #variable [>])*`), for any `IntoIterator`. Note that `Option`s are also `IntoIterator`,
+/// which can help when you want to conditionally include something along with an optional node.
+///
+/// There needs to be one root node, and its type is returned.
+///
+/// Be careful to closely match the Ungrammar AST, there is no validation for this!
+macro_rules! quote_ {
+    ( $root:ident { $($tree:tt)* } ) => {{
+        #[allow(unused_mut)]
+        let mut root = ::std::vec::Vec::<$crate::ast::make::quote::NodeOrToken<
+            $crate::ast::make::quote::GreenNode,
+            $crate::ast::make::quote::GreenToken,
+        >>::with_capacity(1);
+        $crate::ast::make::quote::quote_impl!( @append root $root { $($tree)* } );
+        let root = root.into_iter().next().unwrap();
+        let root = $crate::SyntaxNode::new_root(root.into_node().unwrap());
+        <$crate::ast::$root as $crate::ast::AstNode>::cast(root).unwrap()
+    }};
+}
+pub(crate) use quote_ as quote;
+
+use crate::AstNode;
+
+pub(crate) trait ToNodeChild {
+    fn append_node_child(self, children: &mut Vec<NodeOrToken<GreenNode, GreenToken>>);
+}
+
+impl<N: AstNode> ToNodeChild for N {
+    fn append_node_child(self, children: &mut Vec<NodeOrToken<GreenNode, GreenToken>>) {
+        children.push((*self.syntax().clone_subtree().green()).to_owned().into());
+    }
+}
+
+impl<C: ToNodeChild> ToNodeChild for Option<C> {
+    fn append_node_child(self, children: &mut Vec<NodeOrToken<GreenNode, GreenToken>>) {
+        if let Some(child) = self {
+            child.append_node_child(children);
+        }
+    }
+}
+
+// This is useful when you want conditionally, based on some `bool`, to emit some code.
+impl ToNodeChild for () {
+    fn append_node_child(self, _children: &mut Vec<NodeOrToken<GreenNode, GreenToken>>) {}
+}
+
+pub(crate) const fn verify_only_whitespaces(text: &str) {
+    let text = text.as_bytes();
+    let mut i = 0;
+    while i < text.len() {
+        if !text[i].is_ascii_whitespace() {
+            panic!("non-whitespace found in whitespace token");
+        }
+        i += 1;
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs
index 6ec73e76f78..81c7e15bcbc 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs
@@ -333,7 +333,7 @@ impl ast::Path {
 
 impl ast::Use {
     pub fn is_simple_glob(&self) -> bool {
-        self.use_tree().map_or(false, |use_tree| {
+        self.use_tree().is_some_and(|use_tree| {
             use_tree.use_tree_list().is_none() && use_tree.star_token().is_some()
         })
     }
@@ -387,7 +387,7 @@ impl ast::UseTreeList {
             if let Some((single_subtree,)) = u.use_trees().collect_tuple() {
                 // We have a single subtree, check whether it is self.
 
-                let is_self = single_subtree.path().as_ref().map_or(false, |path| {
+                let is_self = single_subtree.path().as_ref().is_some_and(|path| {
                     path.segment().and_then(|seg| seg.self_token()).is_some()
                         && path.qualifier().is_none()
                 });
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs
index 280c5c25cb9..bea6bfeafcf 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs
@@ -1,6 +1,4 @@
 //! Wrappers over [`make`] constructors
-use itertools::Itertools;
-
 use crate::{
     ast::{self, make, HasGenericParams, HasName, HasTypeBounds, HasVisibility},
     syntax_editor::SyntaxMappingBuilder,
@@ -62,13 +60,12 @@ impl SyntaxFactory {
 
     pub fn block_expr(
         &self,
-        stmts: impl IntoIterator<Item = ast::Stmt>,
+        statements: impl IntoIterator<Item = ast::Stmt>,
         tail_expr: Option<ast::Expr>,
     ) -> ast::BlockExpr {
-        let stmts = stmts.into_iter().collect_vec();
-        let mut input = stmts.iter().map(|it| it.syntax().clone()).collect_vec();
+        let (statements, mut input) = iterator_input(statements);
 
-        let ast = make::block_expr(stmts, tail_expr.clone()).clone_for_update();
+        let ast = make::block_expr(statements, tail_expr.clone()).clone_for_update();
 
         if let Some(mut mapping) = self.mappings() {
             let stmt_list = ast.stmt_list().unwrap();
@@ -257,14 +254,15 @@ impl SyntaxFactory {
 
     pub fn turbofish_generic_arg_list(
         &self,
-        args: impl IntoIterator<Item = ast::GenericArg> + Clone,
+        generic_args: impl IntoIterator<Item = ast::GenericArg>,
     ) -> ast::GenericArgList {
-        let ast = make::turbofish_generic_arg_list(args.clone()).clone_for_update();
+        let (generic_args, input) = iterator_input(generic_args);
+        let ast = make::turbofish_generic_arg_list(generic_args.clone()).clone_for_update();
 
         if let Some(mut mapping) = self.mappings() {
             let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
             builder.map_children(
-                args.into_iter().map(|arg| arg.syntax().clone()),
+                input.into_iter(),
                 ast.generic_args().map(|arg| arg.syntax().clone()),
             );
             builder.finish(&mut mapping);
@@ -277,8 +275,7 @@ impl SyntaxFactory {
         &self,
         fields: impl IntoIterator<Item = ast::RecordField>,
     ) -> ast::RecordFieldList {
-        let fields: Vec<ast::RecordField> = fields.into_iter().collect();
-        let input: Vec<_> = fields.iter().map(|it| it.syntax().clone()).collect();
+        let (fields, input) = iterator_input(fields);
         let ast = make::record_field_list(fields).clone_for_update();
 
         if let Some(mut mapping) = self.mappings() {
@@ -323,8 +320,7 @@ impl SyntaxFactory {
         &self,
         fields: impl IntoIterator<Item = ast::TupleField>,
     ) -> ast::TupleFieldList {
-        let fields: Vec<ast::TupleField> = fields.into_iter().collect();
-        let input: Vec<_> = fields.iter().map(|it| it.syntax().clone()).collect();
+        let (fields, input) = iterator_input(fields);
         let ast = make::tuple_field_list(fields).clone_for_update();
 
         if let Some(mut mapping) = self.mappings() {
@@ -419,8 +415,7 @@ impl SyntaxFactory {
         &self,
         variants: impl IntoIterator<Item = ast::Variant>,
     ) -> ast::VariantList {
-        let variants: Vec<ast::Variant> = variants.into_iter().collect();
-        let input: Vec<_> = variants.iter().map(|it| it.syntax().clone()).collect();
+        let (variants, input) = iterator_input(variants);
         let ast = make::variant_list(variants).clone_for_update();
 
         if let Some(mut mapping) = self.mappings() {
@@ -481,7 +476,7 @@ impl SyntaxFactory {
     pub fn token_tree(
         &self,
         delimiter: SyntaxKind,
-        tt: Vec<NodeOrToken<ast::TokenTree, SyntaxToken>>,
+        tt: impl IntoIterator<Item = NodeOrToken<ast::TokenTree, SyntaxToken>>,
     ) -> ast::TokenTree {
         let tt: Vec<_> = tt.into_iter().collect();
         let input: Vec<_> = tt.iter().cloned().filter_map(only_nodes).collect();
@@ -512,3 +507,20 @@ impl SyntaxFactory {
         make::tokens::whitespace(text)
     }
 }
+
+// We need to collect `input` here instead of taking `impl IntoIterator + Clone`,
+// because if we took `impl IntoIterator + Clone`, that could be something like an
+// `Iterator::map` with a closure that also makes use of a `SyntaxFactory` constructor.
+//
+// In that case, the iterator would be evaluated inside of the call to `map_children`,
+// and the inner constructor would try to take a mutable borrow of the mappings `RefCell`,
+// which would panic since it's already being mutably borrowed in the outer constructor.
+fn iterator_input<N: AstNode>(input: impl IntoIterator<Item = N>) -> (Vec<N>, Vec<SyntaxNode>) {
+    input
+        .into_iter()
+        .map(|it| {
+            let syntax = it.syntax().clone();
+            (it, syntax)
+        })
+        .collect()
+}
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs
index df017ddde64..7d5ca270435 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs
@@ -116,7 +116,7 @@ impl CommentKind {
 impl ast::Whitespace {
     pub fn spans_multiple_lines(&self) -> bool {
         let text = self.text();
-        text.find('\n').map_or(false, |idx| text[idx + 1..].contains('\n'))
+        text.find('\n').is_some_and(|idx| text[idx + 1..].contains('\n'))
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edits.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edits.rs
index 8069fdd06f7..450d601615e 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edits.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edits.rs
@@ -24,7 +24,7 @@ impl SyntaxEditor {
                     if last_param
                         .syntax()
                         .next_sibling_or_token()
-                        .map_or(false, |it| it.kind() == SyntaxKind::COMMA)
+                        .is_some_and(|it| it.kind() == SyntaxKind::COMMA)
                     {
                         self.insert(
                             Position::after(last_param.syntax()),
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 889a7d10ada..0e72d796875 100644
--- a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
@@ -13,16 +13,18 @@ use hir_expand::{
     proc_macro::{
         ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroKind, ProcMacrosBuilder,
     },
-    quote, FileRange,
+    quote,
+    tt::{Leaf, TokenTree, TopSubtree, TopSubtreeBuilder, TtElement, TtIter},
+    FileRange,
 };
 use intern::Symbol;
 use rustc_hash::FxHashMap;
 use span::{Edition, EditionedFileId, FileId, Span};
+use stdx::itertools::Itertools;
 use test_utils::{
     extract_range_or_offset, Fixture, FixtureWithProjectMeta, RangeOrOffset, CURSOR_MARKER,
     ESCAPED_CURSOR_MARKER,
 };
-use tt::{Leaf, Subtree, TokenTree};
 
 pub const WORKSPACE: base_db::SourceRootId = base_db::SourceRootId(0);
 
@@ -374,7 +376,7 @@ impl ChangeFixture {
     }
 }
 
-fn default_test_proc_macros() -> [(String, ProcMacro); 6] {
+fn default_test_proc_macros() -> [(String, ProcMacro); 8] {
     [
         (
             r#"
@@ -466,6 +468,36 @@ pub fn issue_18089(_attr: TokenStream, _item: TokenStream) -> TokenStream {
                 disabled: false,
             },
         ),
+        (
+            r#"
+#[proc_macro_attribute]
+pub fn issue_18840(_attr: TokenStream, _item: TokenStream) -> TokenStream {
+    loop {}
+}
+"#
+            .into(),
+            ProcMacro {
+                name: Symbol::intern("issue_18840"),
+                kind: ProcMacroKind::Attr,
+                expander: sync::Arc::new(Issue18840ProcMacroExpander),
+                disabled: false,
+            },
+        ),
+        (
+            r#"
+#[proc_macro]
+pub fn issue_17479(input: TokenStream) -> TokenStream {
+    input
+}
+"#
+            .into(),
+            ProcMacro {
+                name: Symbol::intern("issue_17479"),
+                kind: ProcMacroKind::Bang,
+                expander: sync::Arc::new(Issue17479ProcMacroExpander),
+                disabled: false,
+            },
+        ),
     ]
 }
 
@@ -580,14 +612,14 @@ struct IdentityProcMacroExpander;
 impl ProcMacroExpander for IdentityProcMacroExpander {
     fn expand(
         &self,
-        subtree: &Subtree<Span>,
-        _: Option<&Subtree<Span>>,
+        subtree: &TopSubtree,
+        _: Option<&TopSubtree>,
         _: &Env,
         _: Span,
         _: Span,
         _: Span,
         _: Option<String>,
-    ) -> Result<Subtree<Span>, ProcMacroExpansionError> {
+    ) -> Result<TopSubtree, ProcMacroExpansionError> {
         Ok(subtree.clone())
     }
 }
@@ -598,15 +630,17 @@ struct Issue18089ProcMacroExpander;
 impl ProcMacroExpander for Issue18089ProcMacroExpander {
     fn expand(
         &self,
-        subtree: &Subtree<Span>,
-        _: Option<&Subtree<Span>>,
+        subtree: &TopSubtree,
+        _: Option<&TopSubtree>,
         _: &Env,
         _: Span,
         call_site: Span,
         _: Span,
         _: Option<String>,
-    ) -> Result<Subtree<Span>, ProcMacroExpansionError> {
-        let macro_name = &subtree.token_trees[1];
+    ) -> Result<TopSubtree, ProcMacroExpansionError> {
+        let tt::TokenTree::Leaf(macro_name) = &subtree.0[2] else {
+            return Err(ProcMacroExpansionError::Panic("incorrect input".to_owned()));
+        };
         Ok(quote! { call_site =>
             #[macro_export]
             macro_rules! my_macro___ {
@@ -627,14 +661,14 @@ struct AttributeInputReplaceProcMacroExpander;
 impl ProcMacroExpander for AttributeInputReplaceProcMacroExpander {
     fn expand(
         &self,
-        _: &Subtree<Span>,
-        attrs: Option<&Subtree<Span>>,
+        _: &TopSubtree,
+        attrs: Option<&TopSubtree>,
         _: &Env,
         _: Span,
         _: Span,
         _: Span,
         _: Option<String>,
-    ) -> Result<Subtree<Span>, ProcMacroExpansionError> {
+    ) -> Result<TopSubtree, ProcMacroExpansionError> {
         attrs
             .cloned()
             .ok_or_else(|| ProcMacroExpansionError::Panic("Expected attribute input".into()))
@@ -642,30 +676,64 @@ impl ProcMacroExpander for AttributeInputReplaceProcMacroExpander {
 }
 
 #[derive(Debug)]
+struct Issue18840ProcMacroExpander;
+impl ProcMacroExpander for Issue18840ProcMacroExpander {
+    fn expand(
+        &self,
+        fn_: &TopSubtree,
+        _: Option<&TopSubtree>,
+        _: &Env,
+        def_site: Span,
+        _: Span,
+        _: Span,
+        _: Option<String>,
+    ) -> Result<TopSubtree, ProcMacroExpansionError> {
+        // Input:
+        // ```
+        // #[issue_18840]
+        // fn foo() { let loop {} }
+        // ```
+
+        // The span that was created by the fixup infra.
+        let fixed_up_span = fn_.token_trees().flat_tokens()[5].first_span();
+        let mut result =
+            quote! {fixed_up_span => ::core::compile_error! { "my cool compile_error!" } };
+        // Make it so we won't remove the top subtree when reversing fixups.
+        let top_subtree_delimiter_mut = result.top_subtree_delimiter_mut();
+        top_subtree_delimiter_mut.open = def_site;
+        top_subtree_delimiter_mut.close = def_site;
+        Ok(result)
+    }
+}
+
+#[derive(Debug)]
 struct MirrorProcMacroExpander;
 impl ProcMacroExpander for MirrorProcMacroExpander {
     fn expand(
         &self,
-        input: &Subtree<Span>,
-        _: Option<&Subtree<Span>>,
+        input: &TopSubtree,
+        _: Option<&TopSubtree>,
         _: &Env,
         _: Span,
         _: Span,
         _: Span,
         _: Option<String>,
-    ) -> Result<Subtree<Span>, ProcMacroExpansionError> {
-        fn traverse(input: &Subtree<Span>) -> Subtree<Span> {
-            let mut token_trees = vec![];
-            for tt in input.token_trees.iter().rev() {
-                let tt = match tt {
-                    tt::TokenTree::Leaf(leaf) => tt::TokenTree::Leaf(leaf.clone()),
-                    tt::TokenTree::Subtree(sub) => tt::TokenTree::Subtree(traverse(sub)),
-                };
-                token_trees.push(tt);
+    ) -> Result<TopSubtree, ProcMacroExpansionError> {
+        fn traverse(builder: &mut TopSubtreeBuilder, iter: TtIter<'_>) {
+            for tt in iter.collect_vec().into_iter().rev() {
+                match tt {
+                    TtElement::Leaf(leaf) => builder.push(leaf.clone()),
+                    TtElement::Subtree(subtree, subtree_iter) => {
+                        builder.open(subtree.delimiter.kind, subtree.delimiter.open);
+                        traverse(builder, subtree_iter);
+                        builder.close(subtree.delimiter.close);
+                    }
+                }
             }
-            Subtree { delimiter: input.delimiter, token_trees: token_trees.into_boxed_slice() }
         }
-        Ok(traverse(input))
+        let mut builder = TopSubtreeBuilder::new(input.top_subtree().delimiter);
+        traverse(&mut builder, input.iter());
+        Ok(builder.build())
     }
 }
 
@@ -677,31 +745,24 @@ struct ShortenProcMacroExpander;
 impl ProcMacroExpander for ShortenProcMacroExpander {
     fn expand(
         &self,
-        input: &Subtree<Span>,
-        _: Option<&Subtree<Span>>,
+        input: &TopSubtree,
+        _: Option<&TopSubtree>,
         _: &Env,
         _: Span,
         _: Span,
         _: Span,
         _: Option<String>,
-    ) -> Result<Subtree<Span>, ProcMacroExpansionError> {
-        return Ok(traverse(input));
-
-        fn traverse(input: &Subtree<Span>) -> Subtree<Span> {
-            let token_trees = input
-                .token_trees
-                .iter()
-                .map(|it| match it {
-                    TokenTree::Leaf(leaf) => tt::TokenTree::Leaf(modify_leaf(leaf)),
-                    TokenTree::Subtree(subtree) => tt::TokenTree::Subtree(traverse(subtree)),
-                })
-                .collect();
-            Subtree { delimiter: input.delimiter, token_trees }
+    ) -> Result<TopSubtree, ProcMacroExpansionError> {
+        let mut result = input.0.clone();
+        for it in &mut result {
+            if let TokenTree::Leaf(leaf) = it {
+                modify_leaf(leaf)
+            }
         }
+        return Ok(tt::TopSubtree(result));
 
-        fn modify_leaf(leaf: &Leaf<Span>) -> Leaf<Span> {
-            let mut leaf = leaf.clone();
-            match &mut leaf {
+        fn modify_leaf(leaf: &mut Leaf) {
+            match leaf {
                 Leaf::Literal(it) => {
                     // XXX Currently replaces any literals with an empty string, but supporting
                     // "shortening" other literals would be nice.
@@ -712,7 +773,31 @@ impl ProcMacroExpander for ShortenProcMacroExpander {
                     it.sym = Symbol::intern(&it.sym.as_str().chars().take(1).collect::<String>());
                 }
             }
-            leaf
         }
     }
 }
+
+// Reads ident type within string quotes, for issue #17479.
+#[derive(Debug)]
+struct Issue17479ProcMacroExpander;
+impl ProcMacroExpander for Issue17479ProcMacroExpander {
+    fn expand(
+        &self,
+        subtree: &TopSubtree,
+        _: Option<&TopSubtree>,
+        _: &Env,
+        _: Span,
+        _: Span,
+        _: Span,
+        _: Option<String>,
+    ) -> Result<TopSubtree, ProcMacroExpansionError> {
+        let TokenTree::Leaf(Leaf::Literal(lit)) = &subtree.0[1] else {
+            return Err(ProcMacroExpansionError::Panic("incorrect Input".into()));
+        };
+        let symbol = &lit.symbol;
+        let span = lit.span;
+        Ok(quote! { span =>
+            #symbol()
+        })
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
index 99dfabe174e..4a2346193b4 100644
--- a/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
+++ b/src/tools/rust-analyzer/crates/test-utils/src/minicore.rs
@@ -17,6 +17,7 @@
 //!     builtin_impls:
 //!     cell: copy, drop
 //!     clone: sized
+//!     coerce_pointee: derive, sized, unsize, coerce_unsized, dispatch_from_dyn
 //!     coerce_unsized: unsize
 //!     concat:
 //!     copy: clone
@@ -157,6 +158,14 @@ pub mod marker {
         type Discriminant;
     }
     // endregion:discriminant
+
+    // region:coerce_pointee
+    #[rustc_builtin_macro(CoercePointee, attributes(pointee))]
+    #[allow_internal_unstable(dispatch_from_dyn, coerce_unsized, unsize)]
+    pub macro CoercePointee($item:item) {
+        /* compiler built-in */
+    }
+    // endregion:coerce_pointee
 }
 
 // region:default
diff --git a/src/tools/rust-analyzer/crates/toolchain/src/lib.rs b/src/tools/rust-analyzer/crates/toolchain/src/lib.rs
index a0603e35a09..325b94cc33b 100644
--- a/src/tools/rust-analyzer/crates/toolchain/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/toolchain/src/lib.rs
@@ -1,6 +1,12 @@
 //! Discovery of `cargo` & `rustc` executables.
 
-use std::{env, iter, path::PathBuf};
+use std::{
+    env,
+    ffi::OsStr,
+    iter,
+    path::{Path, PathBuf},
+    process::Command,
+};
 
 use camino::{Utf8Path, Utf8PathBuf};
 
@@ -65,6 +71,14 @@ impl Tool {
     }
 }
 
+pub fn command(cmd: impl AsRef<OsStr>, working_directory: impl AsRef<Path>) -> Command {
+    // we are `toolchain::command``
+    #[allow(clippy::disallowed_methods)]
+    let mut cmd = Command::new(cmd);
+    cmd.current_dir(working_directory);
+    cmd
+}
+
 fn invoke(list: &[fn(&str) -> Option<Utf8PathBuf>], executable: &str) -> Utf8PathBuf {
     list.iter().find_map(|it| it(executable)).unwrap_or_else(|| executable.into())
 }
@@ -102,7 +116,6 @@ 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))
-        .map(PathBuf::from)
         .map(Utf8PathBuf::try_from)
         .filter_map(Result::ok)
         .find_map(probe_for_binary)
diff --git a/src/tools/rust-analyzer/crates/tt/src/buffer.rs b/src/tools/rust-analyzer/crates/tt/src/buffer.rs
index acb7e2d6c51..02a722895a4 100644
--- a/src/tools/rust-analyzer/crates/tt/src/buffer.rs
+++ b/src/tools/rust-analyzer/crates/tt/src/buffer.rs
@@ -1,259 +1,108 @@
 //! Stateful iteration over token trees.
 //!
 //! We use this as the source of tokens for parser.
-use crate::{Leaf, Subtree, TokenTree};
+use crate::{Leaf, Subtree, TokenTree, TokenTreesView};
 
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
-struct EntryId(usize);
-
-#[derive(Copy, Clone, Debug, Eq, PartialEq)]
-struct EntryPtr(
-    /// The index of the buffer containing the entry.
-    EntryId,
-    /// The index of the entry within the buffer.
-    usize,
-);
-
-/// Internal type which is used instead of `TokenTree` to represent a token tree
-/// within a `TokenBuffer`.
-#[derive(Debug)]
-enum Entry<'t, Span> {
-    // Mimicking types from proc-macro.
-    Subtree(Option<&'t TokenTree<Span>>, &'t Subtree<Span>, EntryId),
-    Leaf(&'t TokenTree<Span>),
-    /// End entries contain a pointer to the entry from the containing
-    /// token tree, or [`None`] if this is the outermost level.
-    End(Option<EntryPtr>),
-}
-
-/// A token tree buffer
-/// The safe version of `syn` [`TokenBuffer`](https://github.com/dtolnay/syn/blob/6533607f91686545cb034d2838beea338d9d0742/src/buffer.rs#L41)
-#[derive(Debug)]
-pub struct TokenBuffer<'t, Span> {
-    buffers: Vec<Box<[Entry<'t, Span>]>>,
-}
-
-trait TokenList<'a, Span> {
-    fn entries(
-        &self,
-    ) -> (Vec<(usize, (&'a Subtree<Span>, Option<&'a TokenTree<Span>>))>, Vec<Entry<'a, Span>>);
-}
-
-impl<'a, Span> TokenList<'a, Span> for &'a [TokenTree<Span>] {
-    fn entries(
-        &self,
-    ) -> (Vec<(usize, (&'a Subtree<Span>, Option<&'a TokenTree<Span>>))>, Vec<Entry<'a, Span>>)
-    {
-        // Must contain everything in tokens and then the Entry::End
-        let start_capacity = self.len() + 1;
-        let mut entries = Vec::with_capacity(start_capacity);
-        let mut children = vec![];
-        for (idx, tt) in self.iter().enumerate() {
-            match tt {
-                TokenTree::Leaf(_) => {
-                    entries.push(Entry::Leaf(tt));
-                }
-                TokenTree::Subtree(subtree) => {
-                    entries.push(Entry::End(None));
-                    children.push((idx, (subtree, Some(tt))));
-                }
-            }
-        }
-        (children, entries)
-    }
-}
-
-impl<'a, Span> TokenList<'a, Span> for &'a Subtree<Span> {
-    fn entries(
-        &self,
-    ) -> (Vec<(usize, (&'a Subtree<Span>, Option<&'a TokenTree<Span>>))>, Vec<Entry<'a, Span>>)
-    {
-        // Must contain everything in tokens and then the Entry::End
-        let mut entries = vec![];
-        let mut children = vec![];
-        entries.push(Entry::End(None));
-        children.push((0usize, (*self, None)));
-        (children, entries)
-    }
-}
-
-impl<'t, Span> TokenBuffer<'t, Span> {
-    pub fn from_tokens(tokens: &'t [TokenTree<Span>]) -> TokenBuffer<'t, Span> {
-        Self::new(tokens)
-    }
-
-    pub fn from_subtree(subtree: &'t Subtree<Span>) -> TokenBuffer<'t, Span> {
-        Self::new(subtree)
-    }
-
-    fn new<T: TokenList<'t, Span>>(tokens: T) -> TokenBuffer<'t, Span> {
-        let mut buffers = vec![];
-        let idx = TokenBuffer::new_inner(tokens, &mut buffers, None);
-        assert_eq!(idx, 0);
-        TokenBuffer { buffers }
-    }
-
-    fn new_inner<T: TokenList<'t, Span>>(
-        tokens: T,
-        buffers: &mut Vec<Box<[Entry<'t, Span>]>>,
-        next: Option<EntryPtr>,
-    ) -> usize {
-        let (children, mut entries) = tokens.entries();
-
-        entries.push(Entry::End(next));
-        let res = buffers.len();
-        buffers.push(entries.into_boxed_slice());
-
-        for (child_idx, (subtree, tt)) in children {
-            let idx = TokenBuffer::new_inner(
-                &*subtree.token_trees,
-                buffers,
-                Some(EntryPtr(EntryId(res), child_idx + 1)),
-            );
-            buffers[res].as_mut()[child_idx] = Entry::Subtree(tt, subtree, EntryId(idx));
-        }
-
-        res
-    }
-
-    /// Creates a cursor referencing the first token in the buffer and able to
-    /// traverse until the end of the buffer.
-    pub fn begin(&self) -> Cursor<'_, Span> {
-        Cursor::create(self, EntryPtr(EntryId(0), 0))
-    }
-
-    fn entry(&self, ptr: &EntryPtr) -> Option<&Entry<'_, Span>> {
-        let id = ptr.0;
-        self.buffers[id.0].get(ptr.1)
-    }
-}
-
-#[derive(Debug)]
-pub enum TokenTreeRef<'a, Span> {
-    Subtree(&'a Subtree<Span>, Option<&'a TokenTree<Span>>),
-    Leaf(&'a Leaf<Span>, &'a TokenTree<Span>),
-}
-
-impl<Span: Copy> TokenTreeRef<'_, Span> {
-    pub fn span(&self) -> Span {
-        match self {
-            TokenTreeRef::Subtree(subtree, _) => subtree.delimiter.open,
-            TokenTreeRef::Leaf(leaf, _) => *leaf.span(),
-        }
-    }
-}
-
-impl<Span: Clone> TokenTreeRef<'_, Span> {
-    pub fn cloned(&self) -> TokenTree<Span> {
-        match self {
-            TokenTreeRef::Subtree(subtree, tt) => match tt {
-                Some(it) => (*it).clone(),
-                None => (*subtree).clone().into(),
-            },
-            TokenTreeRef::Leaf(_, tt) => (*tt).clone(),
-        }
-    }
-}
-
-/// A safe version of `Cursor` from `syn` crate <https://github.com/dtolnay/syn/blob/6533607f91686545cb034d2838beea338d9d0742/src/buffer.rs#L125>
-#[derive(Copy, Clone, Debug)]
 pub struct Cursor<'a, Span> {
-    buffer: &'a TokenBuffer<'a, Span>,
-    ptr: EntryPtr,
+    buffer: &'a [TokenTree<Span>],
+    index: usize,
+    subtrees_stack: Vec<usize>,
 }
 
-impl<Span> PartialEq for Cursor<'_, Span> {
-    fn eq(&self, other: &Cursor<'_, Span>) -> bool {
-        self.ptr == other.ptr && std::ptr::eq(self.buffer, other.buffer)
+impl<'a, Span: Copy> Cursor<'a, Span> {
+    pub fn new(buffer: &'a [TokenTree<Span>]) -> Self {
+        Self { buffer, index: 0, subtrees_stack: Vec::new() }
     }
-}
 
-impl<Span> Eq for Cursor<'_, Span> {}
-
-impl<'a, Span> Cursor<'a, Span> {
     /// Check whether it is eof
-    pub fn eof(self) -> bool {
-        matches!(self.buffer.entry(&self.ptr), None | Some(Entry::End(None)))
+    pub fn eof(&self) -> bool {
+        self.index == self.buffer.len() && self.subtrees_stack.is_empty()
     }
 
-    /// If the cursor is pointing at the end of a subtree, returns
-    /// the parent subtree
-    pub fn end(self) -> Option<&'a Subtree<Span>> {
-        match self.entry() {
-            Some(Entry::End(Some(ptr))) => {
-                let idx = ptr.1;
-                if let Some(Entry::Subtree(_, subtree, _)) =
-                    self.buffer.entry(&EntryPtr(ptr.0, idx - 1))
-                {
-                    return Some(subtree);
-                }
-                None
+    pub fn is_root(&self) -> bool {
+        self.subtrees_stack.is_empty()
+    }
+
+    fn last_subtree(&self) -> Option<(usize, &'a Subtree<Span>)> {
+        self.subtrees_stack.last().map(|&subtree_idx| {
+            let TokenTree::Subtree(subtree) = &self.buffer[subtree_idx] else {
+                panic!("subtree pointing to non-subtree");
+            };
+            (subtree_idx, subtree)
+        })
+    }
+
+    pub fn end(&mut self) -> &'a Subtree<Span> {
+        let (last_subtree_idx, last_subtree) =
+            self.last_subtree().expect("called `Cursor::end()` without an open subtree");
+        // +1 because `Subtree.len` excludes the subtree itself.
+        assert_eq!(
+            last_subtree_idx + last_subtree.usize_len() + 1,
+            self.index,
+            "called `Cursor::end()` without finishing a subtree"
+        );
+        self.subtrees_stack.pop();
+        last_subtree
+    }
+
+    /// Returns the `TokenTree` at the cursor if it is not at the end of a subtree.
+    pub fn token_tree(&self) -> Option<&'a TokenTree<Span>> {
+        if let Some((last_subtree_idx, last_subtree)) = self.last_subtree() {
+            // +1 because `Subtree.len` excludes the subtree itself.
+            if last_subtree_idx + last_subtree.usize_len() + 1 == self.index {
+                return None;
             }
-            _ => None,
         }
+        self.buffer.get(self.index)
     }
 
-    fn entry(&self) -> Option<&'a Entry<'a, Span>> {
-        self.buffer.entry(&self.ptr)
-    }
-
-    /// If the cursor is pointing at a `Subtree`, returns
-    /// a cursor into that subtree
-    pub fn subtree(self) -> Option<Cursor<'a, Span>> {
-        match self.entry() {
-            Some(Entry::Subtree(_, _, entry_id)) => {
-                Some(Cursor::create(self.buffer, EntryPtr(*entry_id, 0)))
-            }
-            _ => None,
+    /// Bump the cursor, and enters a subtree if it is on one.
+    pub fn bump(&mut self) {
+        if let Some((last_subtree_idx, last_subtree)) = self.last_subtree() {
+            // +1 because `Subtree.len` excludes the subtree itself.
+            assert_ne!(
+                last_subtree_idx + last_subtree.usize_len() + 1,
+                self.index,
+                "called `Cursor::bump()` when at the end of a subtree"
+            );
         }
-    }
-
-    /// If the cursor is pointing at a `TokenTree`, returns it
-    pub fn token_tree(self) -> Option<TokenTreeRef<'a, Span>> {
-        match self.entry() {
-            Some(Entry::Leaf(tt)) => match tt {
-                TokenTree::Leaf(leaf) => Some(TokenTreeRef::Leaf(leaf, tt)),
-                TokenTree::Subtree(subtree) => Some(TokenTreeRef::Subtree(subtree, Some(tt))),
-            },
-            Some(Entry::Subtree(tt, subtree, _)) => Some(TokenTreeRef::Subtree(subtree, *tt)),
-            Some(Entry::End(_)) | None => None,
+        if let TokenTree::Subtree(_) = self.buffer[self.index] {
+            self.subtrees_stack.push(self.index);
         }
+        self.index += 1;
     }
 
-    fn create(buffer: &'a TokenBuffer<'_, Span>, ptr: EntryPtr) -> Cursor<'a, Span> {
-        Cursor { buffer, ptr }
-    }
-
-    /// Bump the cursor
-    pub fn bump(self) -> Cursor<'a, Span> {
-        if let Some(Entry::End(exit)) = self.buffer.entry(&self.ptr) {
-            match exit {
-                Some(exit) => Cursor::create(self.buffer, *exit),
-                None => self,
+    pub fn bump_or_end(&mut self) {
+        if let Some((last_subtree_idx, last_subtree)) = self.last_subtree() {
+            // +1 because `Subtree.len` excludes the subtree itself.
+            if last_subtree_idx + last_subtree.usize_len() + 1 == self.index {
+                self.subtrees_stack.pop();
+                return;
             }
-        } else {
-            Cursor::create(self.buffer, EntryPtr(self.ptr.0, self.ptr.1 + 1))
         }
+        // +1 because `Subtree.len` excludes the subtree itself.
+        if let TokenTree::Subtree(_) = self.buffer[self.index] {
+            self.subtrees_stack.push(self.index);
+        }
+        self.index += 1;
     }
 
-    /// Bump the cursor, if it is a subtree, returns
-    /// a cursor into that subtree
-    pub fn bump_subtree(self) -> Cursor<'a, Span> {
-        match self.entry() {
-            Some(&Entry::Subtree(_, _, entry_id)) => {
-                Cursor::create(self.buffer, EntryPtr(entry_id, 0))
+    pub fn peek_two_leaves(&self) -> Option<[&'a Leaf<Span>; 2]> {
+        if let Some((last_subtree_idx, last_subtree)) = self.last_subtree() {
+            // +1 because `Subtree.len` excludes the subtree itself.
+            let last_end = last_subtree_idx + last_subtree.usize_len() + 1;
+            if last_end == self.index || last_end == self.index + 1 {
+                return None;
             }
-            Some(Entry::End(exit)) => match exit {
-                Some(exit) => Cursor::create(self.buffer, *exit),
-                None => self,
-            },
-            _ => Cursor::create(self.buffer, EntryPtr(self.ptr.0, self.ptr.1 + 1)),
         }
+        self.buffer.get(self.index..self.index + 2).and_then(|it| match it {
+            [TokenTree::Leaf(a), TokenTree::Leaf(b)] => Some([a, b]),
+            _ => None,
+        })
     }
 
-    /// Check whether it is a top level
-    pub fn is_root(&self) -> bool {
-        let entry_id = self.ptr.0;
-        entry_id.0 == 0
+    pub fn crossed(&self) -> TokenTreesView<'a, Span> {
+        assert!(self.is_root());
+        TokenTreesView::new(&self.buffer[..self.index])
     }
 }
diff --git a/src/tools/rust-analyzer/crates/tt/src/iter.rs b/src/tools/rust-analyzer/crates/tt/src/iter.rs
index 587b903aa97..1d88218810d 100644
--- a/src/tools/rust-analyzer/crates/tt/src/iter.rs
+++ b/src/tools/rust-analyzer/crates/tt/src/iter.rs
@@ -1,51 +1,64 @@
 //! A "Parser" structure for token trees. We use this when parsing a declarative
 //! macro definition into a list of patterns and templates.
 
+use std::fmt;
+
 use arrayvec::ArrayVec;
 use intern::sym;
 
-use crate::{Ident, Leaf, Punct, Spacing, Subtree, TokenTree};
+use crate::{Ident, Leaf, Punct, Spacing, Subtree, TokenTree, TokenTreesView};
 
-#[derive(Debug, Clone)]
+#[derive(Clone)]
 pub struct TtIter<'a, S> {
     inner: std::slice::Iter<'a, TokenTree<S>>,
 }
 
-impl<'a, S: Copy> TtIter<'a, S> {
-    pub fn new(subtree: &'a Subtree<S>) -> TtIter<'a, S> {
-        TtIter { inner: subtree.token_trees.iter() }
+impl<S: Copy + fmt::Debug> fmt::Debug for TtIter<'_, S> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("TtIter").field("remaining", &self.remaining()).finish()
     }
+}
 
-    pub fn new_iter(iter: std::slice::Iter<'a, TokenTree<S>>) -> TtIter<'a, S> {
-        TtIter { inner: iter }
+#[derive(Clone, Copy)]
+pub struct TtIterSavepoint<'a, S>(&'a [TokenTree<S>]);
+
+impl<'a, S: Copy> TtIterSavepoint<'a, S> {
+    pub fn remaining(self) -> TokenTreesView<'a, S> {
+        TokenTreesView::new(self.0)
+    }
+}
+
+impl<'a, S: Copy> TtIter<'a, S> {
+    pub(crate) fn new(tt: &'a [TokenTree<S>]) -> TtIter<'a, S> {
+        TtIter { inner: tt.iter() }
     }
 
     pub fn expect_char(&mut self, char: char) -> Result<(), ()> {
         match self.next() {
-            Some(&TokenTree::Leaf(Leaf::Punct(Punct { char: c, .. }))) if c == char => Ok(()),
+            Some(TtElement::Leaf(&Leaf::Punct(Punct { char: c, .. }))) if c == char => Ok(()),
             _ => Err(()),
         }
     }
 
     pub fn expect_any_char(&mut self, chars: &[char]) -> Result<(), ()> {
         match self.next() {
-            Some(TokenTree::Leaf(Leaf::Punct(Punct { char: c, .. }))) if chars.contains(c) => {
+            Some(TtElement::Leaf(Leaf::Punct(Punct { char: c, .. }))) if chars.contains(c) => {
                 Ok(())
             }
             _ => Err(()),
         }
     }
 
-    pub fn expect_subtree(&mut self) -> Result<&'a Subtree<S>, ()> {
+    pub fn expect_subtree(&mut self) -> Result<(&'a Subtree<S>, TtIter<'a, S>), ()> {
         match self.next() {
-            Some(TokenTree::Subtree(it)) => Ok(it),
+            Some(TtElement::Subtree(subtree, iter)) => Ok((subtree, iter)),
             _ => Err(()),
         }
     }
 
     pub fn expect_leaf(&mut self) -> Result<&'a Leaf<S>, ()> {
         match self.next() {
-            Some(TokenTree::Leaf(it)) => Ok(it),
+            Some(TtElement::Leaf(it)) => Ok(it),
             _ => Err(()),
         }
     }
@@ -99,7 +112,7 @@ impl<'a, S: Copy> TtIter<'a, S> {
     /// This method currently may return a single quotation, which is part of lifetime ident and
     /// conceptually not a punct in the context of mbe. Callers should handle this.
     pub fn expect_glued_punct(&mut self) -> Result<ArrayVec<Punct<S>, 3>, ()> {
-        let TokenTree::Leaf(Leaf::Punct(first)) = self.next().ok_or(())?.clone() else {
+        let TtElement::Leaf(&Leaf::Punct(first)) = self.next().ok_or(())? else {
             return Err(());
         };
 
@@ -132,6 +145,7 @@ impl<'a, S: Copy> TtIter<'a, S> {
             }
             ('-' | '!' | '*' | '/' | '&' | '%' | '^' | '+' | '<' | '=' | '>' | '|', '=', _)
             | ('-' | '=' | '>', '>', _)
+            | (_, _, Some(';'))
             | ('<', '-', _)
             | (':', ':', _)
             | ('.', '.', _)
@@ -146,28 +160,84 @@ impl<'a, S: Copy> TtIter<'a, S> {
         }
         Ok(res)
     }
-    pub fn peek_n(&self, n: usize) -> Option<&'a TokenTree<S>> {
+
+    /// This method won't check for subtrees, so the nth token tree may not be the nth sibling of the current tree.
+    fn peek_n(&self, n: usize) -> Option<&'a TokenTree<S>> {
         self.inner.as_slice().get(n)
     }
 
+    pub fn peek(&self) -> Option<TtElement<'a, S>> {
+        match self.inner.as_slice().first()? {
+            TokenTree::Leaf(leaf) => Some(TtElement::Leaf(leaf)),
+            TokenTree::Subtree(subtree) => {
+                let nested_iter =
+                    TtIter { inner: self.inner.as_slice()[1..][..subtree.usize_len()].iter() };
+                Some(TtElement::Subtree(subtree, nested_iter))
+            }
+        }
+    }
+
+    /// Equivalent to `peek().is_none()`, but a bit faster.
+    pub fn is_empty(&self) -> bool {
+        self.inner.len() == 0
+    }
+
     pub fn next_span(&self) -> Option<S> {
         Some(self.inner.as_slice().first()?.first_span())
     }
 
-    pub fn as_slice(&self) -> &'a [TokenTree<S>] {
-        self.inner.as_slice()
+    pub fn remaining(&self) -> TokenTreesView<'a, S> {
+        TokenTreesView::new(self.inner.as_slice())
     }
-}
 
-impl<'a, S> Iterator for TtIter<'a, S> {
-    type Item = &'a TokenTree<S>;
-    fn next(&mut self) -> Option<Self::Item> {
-        self.inner.next()
+    /// **Warning**: This advances `skip` **flat** token trees, subtrees account for children+1!
+    pub fn flat_advance(&mut self, skip: usize) {
+        self.inner = self.inner.as_slice()[skip..].iter();
+    }
+
+    pub fn savepoint(&self) -> TtIterSavepoint<'a, S> {
+        TtIterSavepoint(self.inner.as_slice())
+    }
+
+    pub fn from_savepoint(&self, savepoint: TtIterSavepoint<'a, S>) -> TokenTreesView<'a, S> {
+        let len = (self.inner.as_slice().as_ptr() as usize - savepoint.0.as_ptr() as usize)
+            / size_of::<TokenTree<S>>();
+        TokenTreesView::new(&savepoint.0[..len])
     }
 
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        self.inner.size_hint()
+    pub fn next_as_view(&mut self) -> Option<TokenTreesView<'a, S>> {
+        let savepoint = self.savepoint();
+        self.next()?;
+        Some(self.from_savepoint(savepoint))
     }
 }
 
-impl<S> std::iter::ExactSizeIterator for TtIter<'_, S> {}
+pub enum TtElement<'a, S> {
+    Leaf(&'a Leaf<S>),
+    Subtree(&'a Subtree<S>, TtIter<'a, S>),
+}
+
+impl<S: Copy> TtElement<'_, S> {
+    #[inline]
+    pub fn first_span(&self) -> S {
+        match self {
+            TtElement::Leaf(it) => *it.span(),
+            TtElement::Subtree(it, _) => it.delimiter.open,
+        }
+    }
+}
+
+impl<'a, S> Iterator for TtIter<'a, S> {
+    type Item = TtElement<'a, S>;
+    fn next(&mut self) -> Option<Self::Item> {
+        match self.inner.next()? {
+            TokenTree::Leaf(leaf) => Some(TtElement::Leaf(leaf)),
+            TokenTree::Subtree(subtree) => {
+                let nested_iter =
+                    TtIter { inner: self.inner.as_slice()[..subtree.usize_len()].iter() };
+                self.inner = self.inner.as_slice()[subtree.usize_len()..].iter();
+                Some(TtElement::Subtree(subtree, nested_iter))
+            }
+        }
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/tt/src/lib.rs b/src/tools/rust-analyzer/crates/tt/src/lib.rs
index 8d915d0a51e..7705ba876e1 100644
--- a/src/tools/rust-analyzer/crates/tt/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/tt/src/lib.rs
@@ -1,6 +1,7 @@
 //! `tt` crate defines a `TokenTree` data structure: this is the interface (both
-//! input and output) of macros. It closely mirrors `proc_macro` crate's
-//! `TokenTree`.
+//! input and output) of macros.
+//!
+//! The `TokenTree` is semantically a tree, but for performance reasons it is stored as a flat structure.
 
 #![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
 
@@ -14,7 +15,9 @@ pub mod iter;
 
 use std::fmt;
 
+use buffer::Cursor;
 use intern::Symbol;
+use iter::{TtElement, TtIter};
 use stdx::{impl_from, itertools::Itertools as _};
 
 pub use text_size::{TextRange, TextSize};
@@ -75,23 +78,6 @@ pub enum TokenTree<S = u32> {
 }
 impl_from!(Leaf<S>, Subtree<S> for TokenTree);
 impl<S: Copy> TokenTree<S> {
-    pub fn empty(span: S) -> Self {
-        Self::Subtree(Subtree {
-            delimiter: Delimiter::invisible_spanned(span),
-            token_trees: Box::new([]),
-        })
-    }
-
-    pub fn subtree_or_wrap(self, span: DelimSpan<S>) -> Subtree<S> {
-        match self {
-            TokenTree::Leaf(_) => Subtree {
-                delimiter: Delimiter::invisible_delim_spanned(span),
-                token_trees: Box::new([self]),
-            },
-            TokenTree::Subtree(s) => s,
-        }
-    }
-
     pub fn first_span(&self) -> S {
         match self {
             TokenTree::Leaf(l) => *l.span(),
@@ -118,38 +104,422 @@ impl<S> Leaf<S> {
 }
 impl_from!(Literal<S>, Punct<S>, Ident<S> for Leaf);
 
-#[derive(Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Subtree<S> {
     pub delimiter: Delimiter<S>,
-    pub token_trees: Box<[TokenTree<S>]>,
+    /// Number of following token trees that belong to this subtree, excluding this subtree.
+    pub len: u32,
 }
 
-impl<S: Copy> Subtree<S> {
+impl<S> Subtree<S> {
+    pub fn usize_len(&self) -> usize {
+        self.len as usize
+    }
+}
+
+#[derive(Clone, PartialEq, Eq, Hash)]
+pub struct TopSubtree<S>(pub Box<[TokenTree<S>]>);
+
+impl<S: Copy> TopSubtree<S> {
     pub fn empty(span: DelimSpan<S>) -> Self {
-        Subtree { delimiter: Delimiter::invisible_delim_spanned(span), token_trees: Box::new([]) }
+        Self(Box::new([TokenTree::Subtree(Subtree {
+            delimiter: Delimiter::invisible_delim_spanned(span),
+            len: 0,
+        })]))
+    }
+
+    pub fn invisible_from_leaves<const N: usize>(delim_span: S, leaves: [Leaf<S>; N]) -> Self {
+        let mut builder = TopSubtreeBuilder::new(Delimiter::invisible_spanned(delim_span));
+        builder.extend(leaves);
+        builder.build()
+    }
+
+    pub fn from_token_trees(delimiter: Delimiter<S>, token_trees: TokenTreesView<'_, S>) -> Self {
+        let mut builder = TopSubtreeBuilder::new(delimiter);
+        builder.extend_with_tt(token_trees);
+        builder.build()
+    }
+
+    pub fn from_subtree(subtree: SubtreeView<'_, S>) -> Self {
+        Self(subtree.0.into())
+    }
+
+    pub fn view(&self) -> SubtreeView<'_, S> {
+        SubtreeView::new(&self.0)
+    }
+
+    pub fn iter(&self) -> TtIter<'_, S> {
+        self.view().iter()
     }
 
-    /// This is slow, and should be avoided, as it will always reallocate!
-    pub fn push(&mut self, subtree: TokenTree<S>) {
-        let mut mutable_trees = std::mem::take(&mut self.token_trees).into_vec();
+    pub fn top_subtree(&self) -> &Subtree<S> {
+        self.view().top_subtree()
+    }
 
-        // Reserve exactly space for one element, to avoid `into_boxed_slice` having to reallocate again.
-        mutable_trees.reserve_exact(1);
-        mutable_trees.push(subtree);
+    pub fn top_subtree_delimiter_mut(&mut self) -> &mut Delimiter<S> {
+        let TokenTree::Subtree(subtree) = &mut self.0[0] else {
+            unreachable!("the first token tree is always the top subtree");
+        };
+        &mut subtree.delimiter
+    }
 
-        self.token_trees = mutable_trees.into_boxed_slice();
+    pub fn token_trees(&self) -> TokenTreesView<'_, S> {
+        self.view().token_trees()
     }
 }
 
-#[derive(Clone, PartialEq, Eq, Hash)]
-pub struct SubtreeBuilder<S> {
-    pub delimiter: Delimiter<S>,
-    pub token_trees: Vec<TokenTree<S>>,
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct TopSubtreeBuilder<S> {
+    unclosed_subtree_indices: Vec<usize>,
+    token_trees: Vec<TokenTree<S>>,
+    last_closed_subtree: Option<usize>,
+}
+
+impl<S: Copy> TopSubtreeBuilder<S> {
+    pub fn new(top_delimiter: Delimiter<S>) -> Self {
+        let mut result = Self {
+            unclosed_subtree_indices: Vec::new(),
+            token_trees: Vec::new(),
+            last_closed_subtree: None,
+        };
+        let top_subtree = TokenTree::Subtree(Subtree { delimiter: top_delimiter, len: 0 });
+        result.token_trees.push(top_subtree);
+        result
+    }
+
+    pub fn open(&mut self, delimiter_kind: DelimiterKind, open_span: S) {
+        self.unclosed_subtree_indices.push(self.token_trees.len());
+        self.token_trees.push(TokenTree::Subtree(Subtree {
+            delimiter: Delimiter {
+                open: open_span,
+                close: open_span, // Will be overwritten on close.
+                kind: delimiter_kind,
+            },
+            len: 0,
+        }));
+    }
+
+    pub fn close(&mut self, close_span: S) {
+        let last_unclosed_index = self
+            .unclosed_subtree_indices
+            .pop()
+            .expect("attempt to close a `tt::Subtree` when none is open");
+        let subtree_len = (self.token_trees.len() - last_unclosed_index - 1) as u32;
+        let TokenTree::Subtree(subtree) = &mut self.token_trees[last_unclosed_index] else {
+            unreachable!("unclosed token tree is always a subtree");
+        };
+        subtree.len = subtree_len;
+        subtree.delimiter.close = close_span;
+        self.last_closed_subtree = Some(last_unclosed_index);
+    }
+
+    /// You cannot call this consecutively, it will only work once after close.
+    pub fn remove_last_subtree_if_invisible(&mut self) {
+        let Some(last_subtree_idx) = self.last_closed_subtree else { return };
+        if let TokenTree::Subtree(Subtree {
+            delimiter: Delimiter { kind: DelimiterKind::Invisible, .. },
+            ..
+        }) = self.token_trees[last_subtree_idx]
+        {
+            self.token_trees.remove(last_subtree_idx);
+            self.last_closed_subtree = None;
+        }
+    }
+
+    pub fn push(&mut self, leaf: Leaf<S>) {
+        self.token_trees.push(TokenTree::Leaf(leaf));
+    }
+
+    pub fn extend(&mut self, leaves: impl IntoIterator<Item = Leaf<S>>) {
+        self.token_trees.extend(leaves.into_iter().map(TokenTree::Leaf));
+    }
+
+    /// This does not check the token trees are valid, beware!
+    pub fn extend_tt_dangerous(&mut self, tt: impl IntoIterator<Item = TokenTree<S>>) {
+        self.token_trees.extend(tt);
+    }
+
+    pub fn extend_with_tt(&mut self, tt: TokenTreesView<'_, S>) {
+        self.token_trees.extend(tt.0.iter().cloned());
+    }
+
+    pub fn expected_delimiter(&self) -> Option<&Delimiter<S>> {
+        self.unclosed_subtree_indices.last().map(|&subtree_idx| {
+            let TokenTree::Subtree(subtree) = &self.token_trees[subtree_idx] else {
+                unreachable!("unclosed token tree is always a subtree")
+            };
+            &subtree.delimiter
+        })
+    }
+
+    /// Converts unclosed subtree to a punct of their open delimiter.
+    // FIXME: This is incorrect to do, delimiters can never be puncts. See #18244.
+    pub fn flatten_unclosed_subtrees(&mut self) {
+        for &subtree_idx in &self.unclosed_subtree_indices {
+            let TokenTree::Subtree(subtree) = &self.token_trees[subtree_idx] else {
+                unreachable!("unclosed token tree is always a subtree")
+            };
+            let char = match subtree.delimiter.kind {
+                DelimiterKind::Parenthesis => '(',
+                DelimiterKind::Brace => '{',
+                DelimiterKind::Bracket => '[',
+                DelimiterKind::Invisible => '$',
+            };
+            self.token_trees[subtree_idx] = TokenTree::Leaf(Leaf::Punct(Punct {
+                char,
+                spacing: Spacing::Alone,
+                span: subtree.delimiter.open,
+            }));
+        }
+        self.unclosed_subtree_indices.clear();
+    }
+
+    /// Builds, and remove the top subtree if it has only one subtree child.
+    pub fn build_skip_top_subtree(mut self) -> TopSubtree<S> {
+        let top_tts = TokenTreesView::new(&self.token_trees[1..]);
+        match top_tts.try_into_subtree() {
+            Some(_) => {
+                assert!(
+                    self.unclosed_subtree_indices.is_empty(),
+                    "attempt to build an unbalanced `TopSubtreeBuilder`"
+                );
+                TopSubtree(self.token_trees.drain(1..).collect())
+            }
+            None => self.build(),
+        }
+    }
+
+    pub fn build(mut self) -> TopSubtree<S> {
+        assert!(
+            self.unclosed_subtree_indices.is_empty(),
+            "attempt to build an unbalanced `TopSubtreeBuilder`"
+        );
+        let total_len = self.token_trees.len() as u32;
+        let TokenTree::Subtree(top_subtree) = &mut self.token_trees[0] else {
+            unreachable!("first token tree is always a subtree");
+        };
+        top_subtree.len = total_len - 1;
+        TopSubtree(self.token_trees.into_boxed_slice())
+    }
+
+    pub fn restore_point(&self) -> SubtreeBuilderRestorePoint {
+        SubtreeBuilderRestorePoint {
+            unclosed_subtree_indices_len: self.unclosed_subtree_indices.len(),
+            token_trees_len: self.token_trees.len(),
+            last_closed_subtree: self.last_closed_subtree,
+        }
+    }
+
+    pub fn restore(&mut self, restore_point: SubtreeBuilderRestorePoint) {
+        self.unclosed_subtree_indices.truncate(restore_point.unclosed_subtree_indices_len);
+        self.token_trees.truncate(restore_point.token_trees_len);
+        self.last_closed_subtree = restore_point.last_closed_subtree;
+    }
+}
+
+#[derive(Clone, Copy)]
+pub struct SubtreeBuilderRestorePoint {
+    unclosed_subtree_indices_len: usize,
+    token_trees_len: usize,
+    last_closed_subtree: Option<usize>,
+}
+
+#[derive(Clone, Copy)]
+pub struct TokenTreesView<'a, S>(&'a [TokenTree<S>]);
+
+impl<'a, S: Copy> TokenTreesView<'a, S> {
+    pub fn new(tts: &'a [TokenTree<S>]) -> Self {
+        if cfg!(debug_assertions) {
+            tts.iter().enumerate().for_each(|(idx, tt)| {
+                if let TokenTree::Subtree(tt) = &tt {
+                    // `<` and not `<=` because `Subtree.len` does not include the subtree node itself.
+                    debug_assert!(
+                        idx + tt.usize_len() < tts.len(),
+                        "`TokenTreeView::new()` was given a cut-in-half list"
+                    );
+                }
+            });
+        }
+        Self(tts)
+    }
+
+    pub fn iter(&self) -> TtIter<'a, S> {
+        TtIter::new(self.0)
+    }
+
+    pub fn cursor(&self) -> Cursor<'a, S> {
+        Cursor::new(self.0)
+    }
+
+    pub fn len(&self) -> usize {
+        self.0.len()
+    }
+
+    pub fn is_empty(&self) -> bool {
+        self.0.is_empty()
+    }
+
+    pub fn try_into_subtree(self) -> Option<SubtreeView<'a, S>> {
+        if let Some(TokenTree::Subtree(subtree)) = self.0.first() {
+            if subtree.usize_len() == (self.0.len() - 1) {
+                return Some(SubtreeView::new(self.0));
+            }
+        }
+        None
+    }
+
+    pub fn strip_invisible(self) -> TokenTreesView<'a, S> {
+        self.try_into_subtree().map(|subtree| subtree.strip_invisible()).unwrap_or(self)
+    }
+
+    /// This returns a **flat** structure of tokens (subtrees will be represented by a single node
+    /// preceding their children), so it isn't suited for most use cases, only for matching leaves
+    /// at the beginning/end with no subtrees before them. If you need a structured pass, use [`TtIter`].
+    pub fn flat_tokens(&self) -> &'a [TokenTree<S>] {
+        self.0
+    }
+
+    pub fn split(
+        self,
+        mut split_fn: impl FnMut(TtElement<'a, S>) -> bool,
+    ) -> impl Iterator<Item = TokenTreesView<'a, S>> {
+        let mut subtree_iter = self.iter();
+        let mut need_to_yield_even_if_empty = true;
+        let result = std::iter::from_fn(move || {
+            if subtree_iter.is_empty() && !need_to_yield_even_if_empty {
+                return None;
+            };
+
+            need_to_yield_even_if_empty = false;
+            let savepoint = subtree_iter.savepoint();
+            let mut result = subtree_iter.from_savepoint(savepoint);
+            while let Some(tt) = subtree_iter.next() {
+                if split_fn(tt) {
+                    need_to_yield_even_if_empty = true;
+                    break;
+                }
+                result = subtree_iter.from_savepoint(savepoint);
+            }
+            Some(result)
+        });
+        result
+    }
 }
 
-impl<S> SubtreeBuilder<S> {
-    pub fn build(self) -> Subtree<S> {
-        Subtree { delimiter: self.delimiter, token_trees: self.token_trees.into_boxed_slice() }
+impl<S: fmt::Debug + Copy> fmt::Debug for TokenTreesView<'_, S> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut iter = self.iter();
+        while let Some(tt) = iter.next() {
+            print_debug_token(f, 0, tt)?;
+            if !iter.is_empty() {
+                writeln!(f)?;
+            }
+        }
+        Ok(())
+    }
+}
+
+impl<S: Copy> fmt::Display for TokenTreesView<'_, S> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        return token_trees_display(f, self.iter());
+
+        fn subtree_display<S>(
+            subtree: &Subtree<S>,
+            f: &mut fmt::Formatter<'_>,
+            iter: TtIter<'_, S>,
+        ) -> fmt::Result {
+            let (l, r) = match subtree.delimiter.kind {
+                DelimiterKind::Parenthesis => ("(", ")"),
+                DelimiterKind::Brace => ("{", "}"),
+                DelimiterKind::Bracket => ("[", "]"),
+                DelimiterKind::Invisible => ("", ""),
+            };
+            f.write_str(l)?;
+            token_trees_display(f, iter)?;
+            f.write_str(r)?;
+            Ok(())
+        }
+
+        fn token_trees_display<S>(f: &mut fmt::Formatter<'_>, iter: TtIter<'_, S>) -> fmt::Result {
+            let mut needs_space = false;
+            for child in iter {
+                if needs_space {
+                    f.write_str(" ")?;
+                }
+                needs_space = true;
+
+                match child {
+                    TtElement::Leaf(Leaf::Punct(p)) => {
+                        needs_space = p.spacing == Spacing::Alone;
+                        fmt::Display::fmt(p, f)?;
+                    }
+                    TtElement::Leaf(leaf) => fmt::Display::fmt(leaf, f)?,
+                    TtElement::Subtree(subtree, subtree_iter) => {
+                        subtree_display(subtree, f, subtree_iter)?
+                    }
+                }
+            }
+            Ok(())
+        }
+    }
+}
+
+#[derive(Clone, Copy)]
+// Invariant: always starts with `Subtree` that covers the entire thing.
+pub struct SubtreeView<'a, S>(&'a [TokenTree<S>]);
+
+impl<'a, S: Copy> SubtreeView<'a, S> {
+    pub fn new(tts: &'a [TokenTree<S>]) -> Self {
+        if cfg!(debug_assertions) {
+            let TokenTree::Subtree(subtree) = &tts[0] else {
+                panic!("first token tree must be a subtree in `SubtreeView`");
+            };
+            assert_eq!(
+                subtree.usize_len(),
+                tts.len() - 1,
+                "subtree must cover the entire `SubtreeView`"
+            );
+        }
+        Self(tts)
+    }
+
+    pub fn as_token_trees(self) -> TokenTreesView<'a, S> {
+        TokenTreesView::new(self.0)
+    }
+
+    pub fn iter(&self) -> TtIter<'a, S> {
+        TtIter::new(&self.0[1..])
+    }
+
+    pub fn top_subtree(&self) -> &'a Subtree<S> {
+        let TokenTree::Subtree(subtree) = &self.0[0] else {
+            unreachable!("the first token tree is always the top subtree");
+        };
+        subtree
+    }
+
+    pub fn strip_invisible(&self) -> TokenTreesView<'a, S> {
+        if self.top_subtree().delimiter.kind == DelimiterKind::Invisible {
+            TokenTreesView::new(&self.0[1..])
+        } else {
+            TokenTreesView::new(self.0)
+        }
+    }
+
+    pub fn token_trees(&self) -> TokenTreesView<'a, S> {
+        TokenTreesView::new(&self.0[1..])
+    }
+}
+
+impl<S: fmt::Debug + Copy> fmt::Debug for SubtreeView<'_, S> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Debug::fmt(&TokenTreesView(self.0), f)
+    }
+}
+
+impl<S: Copy> fmt::Display for SubtreeView<'_, S> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(&TokenTreesView(self.0), f)
     }
 }
 
@@ -348,6 +718,7 @@ fn print_debug_subtree<S: fmt::Debug>(
     f: &mut fmt::Formatter<'_>,
     subtree: &Subtree<S>,
     level: usize,
+    iter: TtIter<'_, S>,
 ) -> fmt::Result {
     let align = "  ".repeat(level);
 
@@ -363,14 +734,9 @@ fn print_debug_subtree<S: fmt::Debug>(
     fmt::Debug::fmt(&open, f)?;
     write!(f, " ")?;
     fmt::Debug::fmt(&close, f)?;
-    if !subtree.token_trees.is_empty() {
+    for child in iter {
         writeln!(f)?;
-        for (idx, child) in subtree.token_trees.iter().enumerate() {
-            print_debug_token(f, child, level + 1)?;
-            if idx != subtree.token_trees.len() - 1 {
-                writeln!(f)?;
-            }
-        }
+        print_debug_token(f, level + 1, child)?;
     }
 
     Ok(())
@@ -378,13 +744,13 @@ fn print_debug_subtree<S: fmt::Debug>(
 
 fn print_debug_token<S: fmt::Debug>(
     f: &mut fmt::Formatter<'_>,
-    tkn: &TokenTree<S>,
     level: usize,
+    tt: TtElement<'_, S>,
 ) -> fmt::Result {
     let align = "  ".repeat(level);
 
-    match tkn {
-        TokenTree::Leaf(leaf) => match leaf {
+    match tt {
+        TtElement::Leaf(leaf) => match leaf {
             Leaf::Literal(lit) => {
                 write!(
                     f,
@@ -417,54 +783,23 @@ fn print_debug_token<S: fmt::Debug>(
                 )?;
             }
         },
-        TokenTree::Subtree(subtree) => {
-            print_debug_subtree(f, subtree, level)?;
+        TtElement::Subtree(subtree, subtree_iter) => {
+            print_debug_subtree(f, subtree, level, subtree_iter)?;
         }
     }
 
     Ok(())
 }
 
-impl<S: fmt::Debug> fmt::Debug for Subtree<S> {
+impl<S: fmt::Debug + Copy> fmt::Debug for TopSubtree<S> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        print_debug_subtree(f, self, 0)
+        fmt::Debug::fmt(&self.view(), f)
     }
 }
 
-impl<S> fmt::Display for TokenTree<S> {
+impl<S: fmt::Display + Copy> fmt::Display for TopSubtree<S> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            TokenTree::Leaf(it) => fmt::Display::fmt(it, f),
-            TokenTree::Subtree(it) => fmt::Display::fmt(it, f),
-        }
-    }
-}
-
-impl<S> fmt::Display for Subtree<S> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let (l, r) = match self.delimiter.kind {
-            DelimiterKind::Parenthesis => ("(", ")"),
-            DelimiterKind::Brace => ("{", "}"),
-            DelimiterKind::Bracket => ("[", "]"),
-            DelimiterKind::Invisible => ("", ""),
-        };
-        f.write_str(l)?;
-        let mut needs_space = false;
-        for tt in self.token_trees.iter() {
-            if needs_space {
-                f.write_str(" ")?;
-            }
-            needs_space = true;
-            match tt {
-                TokenTree::Leaf(Leaf::Punct(p)) => {
-                    needs_space = p.spacing == Spacing::Alone;
-                    fmt::Display::fmt(p, f)?;
-                }
-                tt => fmt::Display::fmt(tt, f)?,
-            }
-        }
-        f.write_str(r)?;
-        Ok(())
+        fmt::Display::fmt(&self.view(), f)
     }
 }
 
@@ -538,34 +873,45 @@ impl<S> fmt::Display for Punct<S> {
 impl<S> Subtree<S> {
     /// Count the number of tokens recursively
     pub fn count(&self) -> usize {
-        let children_count = self
-            .token_trees
-            .iter()
-            .map(|c| match c {
-                TokenTree::Subtree(c) => c.count(),
-                TokenTree::Leaf(_) => 0,
-            })
-            .sum::<usize>();
-
-        self.token_trees.len() + children_count
+        self.usize_len()
     }
 }
 
-impl<S> Subtree<S> {
+impl<S> TopSubtree<S> {
     /// A simple line string used for debugging
-    pub fn as_debug_string(&self) -> String {
-        let delim = match self.delimiter.kind {
-            DelimiterKind::Brace => ("{", "}"),
-            DelimiterKind::Bracket => ("[", "]"),
-            DelimiterKind::Parenthesis => ("(", ")"),
-            DelimiterKind::Invisible => ("$", "$"),
-        };
+    pub fn subtree_as_debug_string(&self, subtree_idx: usize) -> String {
+        fn debug_subtree<S>(
+            output: &mut String,
+            subtree: &Subtree<S>,
+            iter: &mut std::slice::Iter<'_, TokenTree<S>>,
+        ) {
+            let delim = match subtree.delimiter.kind {
+                DelimiterKind::Brace => ("{", "}"),
+                DelimiterKind::Bracket => ("[", "]"),
+                DelimiterKind::Parenthesis => ("(", ")"),
+                DelimiterKind::Invisible => ("$", "$"),
+            };
 
-        let mut res = String::new();
-        res.push_str(delim.0);
-        let mut last = None;
-        for child in self.token_trees.iter() {
-            let s = match child {
+            output.push_str(delim.0);
+            let mut last = None;
+            let mut idx = 0;
+            while idx < subtree.len {
+                let child = iter.next().unwrap();
+                debug_token_tree(output, child, last, iter);
+                last = Some(child);
+                idx += 1;
+            }
+
+            output.push_str(delim.1);
+        }
+
+        fn debug_token_tree<S>(
+            output: &mut String,
+            tt: &TokenTree<S>,
+            last: Option<&TokenTree<S>>,
+            iter: &mut std::slice::Iter<'_, TokenTree<S>>,
+        ) {
+            match tt {
                 TokenTree::Leaf(it) => {
                     let s = match it {
                         Leaf::Literal(it) => it.symbol.to_string(),
@@ -574,31 +920,37 @@ impl<S> Subtree<S> {
                     };
                     match (it, last) {
                         (Leaf::Ident(_), Some(&TokenTree::Leaf(Leaf::Ident(_)))) => {
-                            " ".to_owned() + &s
+                            output.push(' ');
+                            output.push_str(&s);
                         }
                         (Leaf::Punct(_), Some(TokenTree::Leaf(Leaf::Punct(punct)))) => {
                             if punct.spacing == Spacing::Alone {
-                                " ".to_owned() + &s
+                                output.push(' ');
+                                output.push_str(&s);
                             } else {
-                                s
+                                output.push_str(&s);
                             }
                         }
-                        _ => s,
+                        _ => output.push_str(&s),
                     }
                 }
-                TokenTree::Subtree(it) => it.as_debug_string(),
-            };
-            res.push_str(&s);
-            last = Some(child);
+                TokenTree::Subtree(it) => debug_subtree(output, it, iter),
+            }
         }
 
-        res.push_str(delim.1);
+        let mut res = String::new();
+        debug_token_tree(
+            &mut res,
+            &self.0[subtree_idx],
+            None,
+            &mut self.0[subtree_idx + 1..].iter(),
+        );
         res
     }
 }
 
-pub fn pretty<S>(tkns: &[TokenTree<S>]) -> String {
-    fn tokentree_to_text<S>(tkn: &TokenTree<S>) -> String {
+pub fn pretty<S>(mut tkns: &[TokenTree<S>]) -> String {
+    fn tokentree_to_text<S>(tkn: &TokenTree<S>, tkns: &mut &[TokenTree<S>]) -> String {
         match tkn {
             TokenTree::Leaf(Leaf::Ident(ident)) => {
                 format!("{}{}", ident.is_raw.as_str(), ident.sym)
@@ -606,7 +958,9 @@ pub fn pretty<S>(tkns: &[TokenTree<S>]) -> String {
             TokenTree::Leaf(Leaf::Literal(literal)) => format!("{literal}"),
             TokenTree::Leaf(Leaf::Punct(punct)) => format!("{}", punct.char),
             TokenTree::Subtree(subtree) => {
-                let content = pretty(&subtree.token_trees);
+                let (subtree_content, rest) = tkns.split_at(subtree.usize_len());
+                let content = pretty(subtree_content);
+                *tkns = rest;
                 let (open, close) = match subtree.delimiter.kind {
                     DelimiterKind::Brace => ("{", "}"),
                     DelimiterKind::Bracket => ("[", "]"),
@@ -618,16 +972,18 @@ pub fn pretty<S>(tkns: &[TokenTree<S>]) -> String {
         }
     }
 
-    tkns.iter()
-        .fold((String::new(), true), |(last, last_to_joint), tkn| {
-            let s = [last, tokentree_to_text(tkn)].join(if last_to_joint { "" } else { " " });
-            let mut is_joint = false;
-            if let TokenTree::Leaf(Leaf::Punct(punct)) = tkn {
-                if punct.spacing == Spacing::Joint {
-                    is_joint = true;
-                }
+    let mut last = String::new();
+    let mut last_to_joint = true;
+
+    while let Some((tkn, rest)) = tkns.split_first() {
+        tkns = rest;
+        last = [last, tokentree_to_text(tkn, &mut tkns)].join(if last_to_joint { "" } else { " " });
+        last_to_joint = false;
+        if let TokenTree::Leaf(Leaf::Punct(punct)) = tkn {
+            if punct.spacing == Spacing::Joint {
+                last_to_joint = true;
             }
-            (s, is_joint)
-        })
-        .0
+        }
+    }
+    last
 }
diff --git a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
index 0e37611a549..21ac3a5a269 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: 9790509d87670c22
+lsp/ext.rs hash: 6dd762ae19630ec0
 
 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:
diff --git a/src/tools/rust-analyzer/docs/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc
index 142aa22a704..5b86766aa8e 100644
--- a/src/tools/rust-analyzer/docs/user/generated_config.adoc
+++ b/src/tools/rust-analyzer/docs/user/generated_config.adoc
@@ -135,12 +135,6 @@ Unsetting this disables sysroot loading.
 
 This option does not take effect until rust-analyzer is restarted.
 --
-[[rust-analyzer.cargo.sysrootQueryMetadata]]rust-analyzer.cargo.sysrootQueryMetadata (default: `"cargo_metadata"`)::
-+
---
-How to query metadata for the sysroot crate. Using cargo metadata allows rust-analyzer
-to analyze third-party dependencies of the standard libraries.
---
 [[rust-analyzer.cargo.sysrootSrc]]rust-analyzer.cargo.sysrootSrc (default: `null`)::
 +
 --
@@ -152,7 +146,7 @@ This option does not take effect until rust-analyzer is restarted.
 [[rust-analyzer.cargo.target]]rust-analyzer.cargo.target (default: `null`)::
 +
 --
-Compilation target override (target triple).
+Compilation target override (target tuple).
 --
 [[rust-analyzer.cargo.targetDir]]rust-analyzer.cargo.targetDir (default: `null`)::
 +
@@ -286,6 +280,35 @@ In `match` arms it completes a comma instead.
 Toggles the additional completions that automatically add imports when completed.
 Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
 --
+[[rust-analyzer.completion.autoimport.exclude]]rust-analyzer.completion.autoimport.exclude::
++
+--
+Default:
+----
+[
+  {
+    "path": "core::borrow::Borrow",
+    "type": "methods"
+  },
+  {
+    "path": "core::borrow::BorrowMut",
+    "type": "methods"
+  }
+]
+----
+A list of full paths to items to exclude from auto-importing completions.
+
+Traits in this list won't have their methods suggested in completions unless the trait
+is in scope.
+
+You can either specify a string path which defaults to type "always" or use the more verbose
+form `{ "path": "path::to::item", type: "always" }`.
+
+For traits the type "methods" can be used to only exclude the methods but not the trait itself.
+
+This setting also inherits `#rust-analyzer.completion.excludeTraits#`.
+
+--
 [[rust-analyzer.completion.autoself.enable]]rust-analyzer.completion.autoself.enable (default: `true`)::
 +
 --
@@ -297,6 +320,15 @@ with `self` prefixed to them when inside a method.
 --
 Whether to add parenthesis and argument snippets when completing function.
 --
+[[rust-analyzer.completion.excludeTraits]]rust-analyzer.completion.excludeTraits (default: `[]`)::
++
+--
+A list of full paths to traits whose methods to exclude from completion.
+
+Methods from these traits won't be completed, even if the trait is in scope. However, they will still be suggested on expressions whose type is `dyn Trait`, `impl Trait` or `T where T: Trait`.
+
+Note that the trait themselves can still be completed.
+--
 [[rust-analyzer.completion.fullFunctionSignatures.enable]]rust-analyzer.completion.fullFunctionSignatures.enable (default: `false`)::
 +
 --
@@ -497,6 +529,12 @@ Whether to show `References` action. Only applies when
 Whether to show `Run` action. Only applies when
 `#rust-analyzer.hover.actions.enable#` is set.
 --
+[[rust-analyzer.hover.actions.updateTest.enable]]rust-analyzer.hover.actions.updateTest.enable (default: `true`)::
++
+--
+Whether to show `Update Test` action. Only applies when
+`#rust-analyzer.hover.actions.enable#` and `#rust-analyzer.hover.actions.run.enable#` are set.
+--
 [[rust-analyzer.hover.documentation.enable]]rust-analyzer.hover.documentation.enable (default: `true`)::
 +
 --
@@ -513,6 +551,15 @@ Whether to show keyword hover popups. Only applies when
 --
 Use markdown syntax for links on hover.
 --
+[[rust-analyzer.hover.maxSubstitutionLength]]rust-analyzer.hover.maxSubstitutionLength (default: `20`)::
++
+--
+Whether to show what types are used as generic arguments in calls etc. on hover, and what is their max length to show such types, beyond it they will be shown with ellipsis.
+
+This can take three values: `null` means "unlimited", the string `"hide"` means to not show generic substitutions at all, and a number means to limit them to X characters.
+
+The default is 20 characters.
+--
 [[rust-analyzer.hover.memoryLayout.alignment]]rust-analyzer.hover.memoryLayout.alignment (default: `"hexadecimal"`)::
 +
 --
@@ -799,6 +846,12 @@ Only applies when `#rust-analyzer.lens.enable#` is set.
 Whether to show `Run` lens. Only applies when
 `#rust-analyzer.lens.enable#` is set.
 --
+[[rust-analyzer.lens.updateTest.enable]]rust-analyzer.lens.updateTest.enable (default: `true`)::
++
+--
+Whether to show `Update Test` lens. Only applies when
+`#rust-analyzer.lens.enable#` and `#rust-analyzer.lens.run.enable#` are set.
+--
 [[rust-analyzer.linkedProjects]]rust-analyzer.linkedProjects (default: `[]`)::
 +
 --
diff --git a/src/tools/rust-analyzer/docs/user/manual.adoc b/src/tools/rust-analyzer/docs/user/manual.adoc
index da2aa4eae4e..ffc820e9b7f 100644
--- a/src/tools/rust-analyzer/docs/user/manual.adoc
+++ b/src/tools/rust-analyzer/docs/user/manual.adoc
@@ -769,7 +769,7 @@ interface Crate {
     /// The set of cfgs activated for a given crate, like
     /// `["unix", "feature=\"foo\"", "feature=\"bar\""]`.
     cfg: string[];
-    /// Target triple for this Crate.
+    /// Target tuple for this Crate.
     ///
     /// Used when running `rustc --print cfg`
     /// to get target-specific cfgs.
diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json
index df97efaae73..80246bf3fea 100644
--- a/src/tools/rust-analyzer/editors/code/package.json
+++ b/src/tools/rust-analyzer/editors/code/package.json
@@ -407,6 +407,11 @@
                             "$rustc"
                         ],
                         "markdownDescription": "Problem matchers to use for `rust-analyzer.run` command, eg `[\"$rustc\", \"$rust-panic\"]`."
+                    },
+                    "rust-analyzer.runnables.askBeforeUpdateTest": {
+                        "type": "boolean",
+                        "default": true,
+                        "markdownDescription": "Ask before updating the test when running it."
                     }
                 }
             },
@@ -426,40 +431,55 @@
                         "default": "openLogs",
                         "markdownDescription": "Action to run when clicking the extension status bar item."
                     },
-                    "rust-analyzer.statusBar.documentSelector": {
-                        "type": [
-                            "array",
-                            "null"
-                        ],
-                        "items": {
-                            "type": "object",
-                            "properties": {
-                                "language": {
-                                    "type": [
-                                        "string",
-                                        "null"
-                                    ]
-                                },
-                                "pattern": {
-                                    "type": [
-                                        "string",
-                                        "null"
-                                    ]
-                                }
-                            }
-                        },
-                        "default": [
-                            {
-                                "language": "rust"
-                            },
+                    "rust-analyzer.statusBar.showStatusBar": {
+                        "markdownDescription": "When to show the extension status bar.\n\n`\"always\"` Always show the status bar.\n\n`\"never\"` Never show the status bar.\n\n`{ documentSelector: <DocumentSelector>[] }` Show the status bar if the open file matches any of the given document selectors.\n\nSee [VS Code -- DocumentSelector](https://code.visualstudio.com/api/references/document-selector) for more information.",
+                        "anyOf": [
                             {
-                                "pattern": "**/Cargo.toml"
+                                "type": "string",
+                                "enum": [
+                                    "always",
+                                    "never"
+                                ]
                             },
                             {
-                                "pattern": "**/Cargo.lock"
+                                "type": "object",
+                                "properties": {
+                                    "documentSelector": {
+                                        "type": "array",
+                                        "items": {
+                                            "type": "object",
+                                            "properties": {
+                                                "language": {
+                                                    "type": "string"
+                                                },
+                                                "notebookType": {
+                                                    "type": "string"
+                                                },
+                                                "scheme": {
+                                                    "type": "string"
+                                                },
+                                                "pattern": {
+                                                    "type": "string"
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
                             }
                         ],
-                        "markdownDescription": "Determines when to show the extension status bar item based on the currently open file. Use `{ \"pattern\": \"**\" }` to always show. Use `null` to never show."
+                        "default": {
+                            "documentSelector": [
+                                {
+                                    "language": "rust"
+                                },
+                                {
+                                    "pattern": "**/Cargo.toml"
+                                },
+                                {
+                                    "pattern": "**/Cargo.lock"
+                                }
+                            ]
+                        }
                     }
                 }
             },
@@ -854,24 +874,6 @@
             {
                 "title": "cargo",
                 "properties": {
-                    "rust-analyzer.cargo.sysrootQueryMetadata": {
-                        "markdownDescription": "How to query metadata for the sysroot crate. Using cargo metadata allows rust-analyzer\nto analyze third-party dependencies of the standard libraries.",
-                        "default": "cargo_metadata",
-                        "type": "string",
-                        "enum": [
-                            "none",
-                            "cargo_metadata"
-                        ],
-                        "enumDescriptions": [
-                            "Do not query sysroot metadata, always use stitched sysroot.",
-                            "Use `cargo metadata` to query sysroot metadata."
-                        ]
-                    }
-                }
-            },
-            {
-                "title": "cargo",
-                "properties": {
                     "rust-analyzer.cargo.sysrootSrc": {
                         "markdownDescription": "Relative path to the sysroot library sources. If left unset, this will default to\n`{cargo.sysroot}/lib/rustlib/src/rust/library`.\n\nThis option does not take effect until rust-analyzer is restarted.",
                         "default": null,
@@ -886,7 +888,7 @@
                 "title": "cargo",
                 "properties": {
                     "rust-analyzer.cargo.target": {
-                        "markdownDescription": "Compilation target override (target triple).",
+                        "markdownDescription": "Compilation target override (target tuple).",
                         "default": null,
                         "type": [
                             "null",
@@ -1127,6 +1129,51 @@
             {
                 "title": "completion",
                 "properties": {
+                    "rust-analyzer.completion.autoimport.exclude": {
+                        "markdownDescription": "A list of full paths to items to exclude from auto-importing completions.\n\nTraits in this list won't have their methods suggested in completions unless the trait\nis in scope.\n\nYou can either specify a string path which defaults to type \"always\" or use the more verbose\nform `{ \"path\": \"path::to::item\", type: \"always\" }`.\n\nFor traits the type \"methods\" can be used to only exclude the methods but not the trait itself.\n\nThis setting also inherits `#rust-analyzer.completion.excludeTraits#`.",
+                        "default": [
+                            {
+                                "path": "core::borrow::Borrow",
+                                "type": "methods"
+                            },
+                            {
+                                "path": "core::borrow::BorrowMut",
+                                "type": "methods"
+                            }
+                        ],
+                        "type": "array",
+                        "items": {
+                            "anyOf": [
+                                {
+                                    "type": "string"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "path": {
+                                            "type": "string"
+                                        },
+                                        "type": {
+                                            "type": "string",
+                                            "enum": [
+                                                "always",
+                                                "methods"
+                                            ],
+                                            "enumDescriptions": [
+                                                "Do not show this item or its methods (if it is a trait) in auto-import completions.",
+                                                "Do not show this traits methods in auto-import completions."
+                                            ]
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            },
+            {
+                "title": "completion",
+                "properties": {
                     "rust-analyzer.completion.autoself.enable": {
                         "markdownDescription": "Toggles the additional completions that automatically show method calls and field accesses\nwith `self` prefixed to them when inside a method.",
                         "default": true,
@@ -1157,6 +1204,19 @@
             {
                 "title": "completion",
                 "properties": {
+                    "rust-analyzer.completion.excludeTraits": {
+                        "markdownDescription": "A list of full paths to traits whose methods to exclude from completion.\n\nMethods from these traits won't be completed, even if the trait is in scope. However, they will still be suggested on expressions whose type is `dyn Trait`, `impl Trait` or `T where T: Trait`.\n\nNote that the trait themselves can still be completed.",
+                        "default": [],
+                        "type": "array",
+                        "items": {
+                            "type": "string"
+                        }
+                    }
+                }
+            },
+            {
+                "title": "completion",
+                "properties": {
                     "rust-analyzer.completion.fullFunctionSignatures.enable": {
                         "markdownDescription": "Whether to show full function/method signatures in completion docs.",
                         "default": false,
@@ -1503,6 +1563,16 @@
             {
                 "title": "hover",
                 "properties": {
+                    "rust-analyzer.hover.actions.updateTest.enable": {
+                        "markdownDescription": "Whether to show `Update Test` action. Only applies when\n`#rust-analyzer.hover.actions.enable#` and `#rust-analyzer.hover.actions.run.enable#` are set.",
+                        "default": true,
+                        "type": "boolean"
+                    }
+                }
+            },
+            {
+                "title": "hover",
+                "properties": {
                     "rust-analyzer.hover.documentation.enable": {
                         "markdownDescription": "Whether to show documentation on hover.",
                         "default": true,
@@ -1533,6 +1603,29 @@
             {
                 "title": "hover",
                 "properties": {
+                    "rust-analyzer.hover.maxSubstitutionLength": {
+                        "markdownDescription": "Whether to show what types are used as generic arguments in calls etc. on hover, and what is their max length to show such types, beyond it they will be shown with ellipsis.\n\nThis can take three values: `null` means \"unlimited\", the string `\"hide\"` means to not show generic substitutions at all, and a number means to limit them to X characters.\n\nThe default is 20 characters.",
+                        "default": 20,
+                        "anyOf": [
+                            {
+                                "type": "null"
+                            },
+                            {
+                                "type": "string",
+                                "enum": [
+                                    "hide"
+                                ]
+                            },
+                            {
+                                "type": "integer"
+                            }
+                        ]
+                    }
+                }
+            },
+            {
+                "title": "hover",
+                "properties": {
                     "rust-analyzer.hover.memoryLayout.alignment": {
                         "markdownDescription": "How to render the align information in a memory layout hover.",
                         "default": "hexadecimal",
@@ -2258,6 +2351,16 @@
                 }
             },
             {
+                "title": "lens",
+                "properties": {
+                    "rust-analyzer.lens.updateTest.enable": {
+                        "markdownDescription": "Whether to show `Update Test` lens. Only applies when\n`#rust-analyzer.lens.enable#` and `#rust-analyzer.lens.run.enable#` are set.",
+                        "default": true,
+                        "type": "boolean"
+                    }
+                }
+            },
+            {
                 "title": "general",
                 "properties": {
                     "rust-analyzer.linkedProjects": {
diff --git a/src/tools/rust-analyzer/editors/code/src/commands.ts b/src/tools/rust-analyzer/editors/code/src/commands.ts
index 7ebc186a3ea..73e39c900e7 100644
--- a/src/tools/rust-analyzer/editors/code/src/commands.ts
+++ b/src/tools/rust-analyzer/editors/code/src/commands.ts
@@ -1139,11 +1139,37 @@ export function peekTests(ctx: CtxInit): Cmd {
     };
 }
 
+function isUpdatingTest(runnable: ra.Runnable): boolean {
+    if (!isCargoRunnableArgs(runnable.args)) {
+        return false;
+    }
+
+    const env = runnable.args.environment;
+    return env ? ["UPDATE_EXPECT", "INSTA_UPDATE", "SNAPSHOTS"].some((key) => key in env) : false;
+}
+
 export function runSingle(ctx: CtxInit): Cmd {
     return async (runnable: ra.Runnable) => {
         const editor = ctx.activeRustEditor;
         if (!editor) return;
 
+        if (isUpdatingTest(runnable) && ctx.config.askBeforeUpdateTest) {
+            const selection = await vscode.window.showInformationMessage(
+                "rust-analyzer",
+                { detail: "Do you want to update tests?", modal: true },
+                "Update Now",
+                "Update (and Don't ask again)",
+            );
+
+            if (selection !== "Update Now" && selection !== "Update (and Don't ask again)") {
+                return;
+            }
+
+            if (selection === "Update (and Don't ask again)") {
+                await ctx.config.setAskBeforeUpdateTest(false);
+            }
+        }
+
         const task = await createTaskFromRunnable(runnable, ctx.config);
         task.group = vscode.TaskGroup.Build;
         task.presentationOptions = {
diff --git a/src/tools/rust-analyzer/editors/code/src/config.ts b/src/tools/rust-analyzer/editors/code/src/config.ts
index f7ef80df2ba..720c473c5b4 100644
--- a/src/tools/rust-analyzer/editors/code/src/config.ts
+++ b/src/tools/rust-analyzer/editors/code/src/config.ts
@@ -13,6 +13,13 @@ export type RunnableEnvCfgItem = {
 };
 export type RunnableEnvCfg = Record<string, string> | RunnableEnvCfgItem[];
 
+type ShowStatusBar =
+    | "always"
+    | "never"
+    | {
+          documentSelector: vscode.DocumentSelector;
+      };
+
 export class Config {
     readonly extensionId = "rust-lang.rust-analyzer";
     configureLang: vscode.Disposable | undefined;
@@ -348,13 +355,20 @@ export class Config {
         return this.get<string>("statusBar.clickAction");
     }
 
-    get statusBarDocumentSelector() {
-        return this.get<vscode.DocumentSelector>("statusBar.documentSelector");
+    get statusBarShowStatusBar() {
+        return this.get<ShowStatusBar>("statusBar.showStatusBar");
     }
 
     get initializeStopped() {
         return this.get<boolean>("initializeStopped");
     }
+
+    get askBeforeUpdateTest() {
+        return this.get<boolean>("runnables.askBeforeUpdateTest");
+    }
+    async setAskBeforeUpdateTest(value: boolean) {
+        await this.cfg.update("runnables.askBeforeUpdateTest", value, true);
+    }
 }
 
 export function prepareVSCodeConfig<T>(resp: T): T {
diff --git a/src/tools/rust-analyzer/editors/code/src/ctx.ts b/src/tools/rust-analyzer/editors/code/src/ctx.ts
index 459754b1d1c..37a54abf71f 100644
--- a/src/tools/rust-analyzer/editors/code/src/ctx.ts
+++ b/src/tools/rust-analyzer/editors/code/src/ctx.ts
@@ -480,14 +480,19 @@ export class Ctx implements RustAnalyzerExtensionApi {
     }
 
     private updateStatusBarVisibility(editor: vscode.TextEditor | undefined) {
-        const documentSelector = this.config.statusBarDocumentSelector;
-        if (documentSelector != null) {
+        const showStatusBar = this.config.statusBarShowStatusBar;
+        if (showStatusBar == null || showStatusBar === "never") {
+            this.statusBar.hide();
+        } else if (showStatusBar === "always") {
+            this.statusBar.show();
+        } else {
+            const documentSelector = showStatusBar.documentSelector;
             if (editor != null && vscode.languages.match(documentSelector, editor.document) > 0) {
                 this.statusBar.show();
-                return;
+            } else {
+                this.statusBar.hide();
             }
         }
-        this.statusBar.hide();
     }
 
     pushExtCleanup(d: Disposable) {
diff --git a/src/tools/rust-analyzer/rust-version b/src/tools/rust-analyzer/rust-version
index 3be63741c00..517fdfe18ed 100644
--- a/src/tools/rust-analyzer/rust-version
+++ b/src/tools/rust-analyzer/rust-version
@@ -1 +1 @@
-0eca4dd3205a01dba4bd7b7c140ec370aff03440
+fb546ee09b226bc4dd4b712d35a372d923c4fa54
diff --git a/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs b/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs
index e7534582f2b..d5fe3236789 100644
--- a/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs
+++ b/src/tools/rust-analyzer/xtask/src/codegen/grammar.rs
@@ -163,6 +163,13 @@ fn generate_nodes(kinds: KindsSrc, grammar: &AstSrc) -> String {
                 quote! {
                     impl AstNode for #name {
                         #[inline]
+                        fn kind() -> SyntaxKind
+                        where
+                            Self: Sized
+                        {
+                            #kind
+                        }
+                        #[inline]
                         fn can_cast(kind: SyntaxKind) -> bool {
                             kind == #kind
                         }
@@ -397,6 +404,7 @@ fn generate_syntax_kinds(grammar: KindsSrc) -> String {
     });
     let punctuation =
         grammar.punct.iter().map(|(_token, name)| format_ident!("{}", name)).collect::<Vec<_>>();
+    let punctuation_texts = grammar.punct.iter().map(|&(text, _name)| text);
 
     let fmt_kw_as_variant = |&name| match name {
         "Self" => format_ident!("SELF_TYPE_KW"),
@@ -422,6 +430,7 @@ fn generate_syntax_kinds(grammar: KindsSrc) -> String {
             quote! { #kw if #ed <= edition }
         })
         .collect::<Vec<_>>();
+    let edition_dependent_keywords = grammar.edition_dependent_keywords.iter().map(|&(it, _)| it);
     let edition_dependent_keywords_variants = grammar
         .edition_dependent_keywords
         .iter()
@@ -495,6 +504,20 @@ fn generate_syntax_kinds(grammar: KindsSrc) -> String {
         use self::SyntaxKind::*;
 
         impl SyntaxKind {
+            #[allow(unreachable_patterns)]
+            pub const fn text(self) -> &'static str {
+                match self {
+                    TOMBSTONE | EOF | __LAST
+                    #( | #literals )*
+                    #( | #nodes )*
+                    #( | #tokens )* => panic!("no text for these `SyntaxKind`s"),
+                    #( #punctuation => #punctuation_texts ,)*
+                    #( #strict_keywords_variants => #strict_keywords ,)*
+                    #( #contextual_keywords_variants => #contextual_keywords ,)*
+                    #( #edition_dependent_keywords_variants => #edition_dependent_keywords ,)*
+                }
+            }
+
             /// Checks whether this syntax kind is a strict keyword for the given edition.
             /// Strict keywords are identifiers that are always considered keywords.
             pub fn is_strict_keyword(self, edition: Edition) -> bool {
@@ -861,7 +884,7 @@ fn lower_separated_list(
     if !matches!(
         repeat.as_slice(),
         [comma, nt_]
-            if trailing_sep.map_or(true, |it| comma == &**it) && match (nt, nt_) {
+            if trailing_sep.is_none_or(|it| comma == &**it) && match (nt, nt_) {
                 (Either::Left(node), Rule::Node(nt_)) => node == nt_,
                 (Either::Right(token), Rule::Token(nt_)) => token == nt_,
                 _ => false,
diff --git a/src/tools/rust-analyzer/xtask/src/main.rs b/src/tools/rust-analyzer/xtask/src/main.rs
index 5c312da1dd7..1e723b90a5e 100644
--- a/src/tools/rust-analyzer/xtask/src/main.rs
+++ b/src/tools/rust-analyzer/xtask/src/main.rs
@@ -9,7 +9,12 @@
 //! `.cargo/config`.
 
 #![warn(rust_2018_idioms, unused_lifetimes)]
-#![allow(clippy::print_stderr, clippy::print_stdout)]
+#![allow(
+    clippy::print_stderr,
+    clippy::print_stdout,
+    clippy::disallowed_methods,
+    clippy::disallowed_types
+)]
 
 mod flags;