about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2025-03-06 05:58:06 +0000
committerGitHub <noreply@github.com>2025-03-06 05:58:06 +0000
commitb178f22bd8267155f2e330731a53ef3e4eac28bb (patch)
treef861f7c201007112dc2f2f016855c7e0529e9cc0 /src
parent14cfc3ade4538ecf6f684962521685664348b522 (diff)
parentf80cac723acf10a8f9fd05b335ed5797e4f69a1a (diff)
downloadrust-b178f22bd8267155f2e330731a53ef3e4eac28bb.tar.gz
rust-b178f22bd8267155f2e330731a53ef3e4eac28bb.zip
Merge pull request #4220 from rust-lang/rustup-2025-03-06
Automatic Rustup
Diffstat (limited to 'src')
-rwxr-xr-xsrc/bootstrap/configure.py2
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs6
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs27
-rw-r--r--src/bootstrap/src/core/build_steps/setup.rs5
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs178
-rw-r--r--src/bootstrap/src/core/build_steps/tool.rs90
-rw-r--r--src/bootstrap/src/core/builder/mod.rs1
-rw-r--r--src/bootstrap/src/core/builder/tests.rs47
-rw-r--r--src/bootstrap/src/core/config/config.rs13
-rw-r--r--src/bootstrap/src/core/metadata.rs8
-rw-r--r--src/bootstrap/src/lib.rs1
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs5
-rw-r--r--src/bootstrap/src/utils/metrics.rs8
-rw-r--r--src/build_helper/src/metrics.rs88
-rw-r--r--src/ci/citool/Cargo.lock1098
-rw-r--r--src/ci/citool/Cargo.toml27
-rw-r--r--src/ci/citool/README.md2
-rw-r--r--src/ci/citool/src/cpu_usage.rs24
-rw-r--r--src/ci/citool/src/datadog.rs43
-rw-r--r--src/ci/citool/src/main.rs412
-rw-r--r--src/ci/citool/src/metrics.rs164
-rw-r--r--src/ci/citool/src/utils.rs11
-rw-r--r--src/ci/citool/tests/jobs.rs64
-rw-r--r--src/ci/citool/tests/test-jobs.yml145
-rw-r--r--src/ci/docker/README.md6
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile2
-rwxr-xr-xsrc/ci/docker/scripts/rfl-build.sh18
-rwxr-xr-xsrc/ci/github-actions/ci.py318
-rw-r--r--src/ci/github-actions/jobs.yml2
-rw-r--r--src/ci/package-lock.json5004
-rw-r--r--src/ci/package.json5
-rw-r--r--src/ci/scripts/upload-build-metrics.py86
-rw-r--r--src/doc/rustc-dev-guide/src/building/optimized-build.md2
-rw-r--r--src/doc/rustc-dev-guide/src/parallel-rustc.md2
-rw-r--r--src/doc/rustc-dev-guide/src/tests/ci.md6
-rw-r--r--src/doc/rustc-dev-guide/src/tests/compiletest.md30
-rw-r--r--src/doc/rustc-dev-guide/src/tests/directives.md8
-rw-r--r--src/doc/rustc-dev-guide/src/tests/docker.md9
-rw-r--r--src/doc/rustc-dev-guide/src/tests/running.md25
-rw-r--r--src/doc/rustc/src/SUMMARY.md1
-rw-r--r--src/doc/rustc/src/platform-support.md2
-rw-r--r--src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-gnu.md2
-rw-r--r--src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md2
-rw-r--r--src/doc/rustc/src/platform-support/wasm64-unknown-unknown.md2
-rw-r--r--src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md27
-rwxr-xr-xsrc/etc/htmldocck.py14
-rwxr-xr-xsrc/etc/pre-push.sh14
-rw-r--r--src/etc/test-float-parse/src/gen/exhaustive.rs3
-rw-r--r--src/etc/test-float-parse/src/gen/fuzz.rs1
-rw-r--r--src/etc/test-float-parse/src/gen/sparse.rs1
-rw-r--r--src/etc/test-float-parse/src/lib.rs221
-rw-r--r--src/etc/test-float-parse/src/traits.rs8
-rw-r--r--src/etc/test-float-parse/src/ui.rs126
-rw-r--r--src/etc/test-float-parse/src/validate.rs46
-rw-r--r--src/librustdoc/Cargo.toml2
-rw-r--r--src/librustdoc/clean/cfg.rs4
-rw-r--r--src/librustdoc/clean/mod.rs4
-rw-r--r--src/librustdoc/clean/render_macro_matchers.rs13
-rw-r--r--src/librustdoc/clean/types.rs8
-rw-r--r--src/librustdoc/clean/utils.rs13
-rw-r--r--src/librustdoc/config.rs28
-rw-r--r--src/librustdoc/core.rs24
-rw-r--r--src/librustdoc/html/format.rs160
-rw-r--r--src/librustdoc/html/render/context.rs5
-rw-r--r--src/librustdoc/html/render/mod.rs1483
-rw-r--r--src/librustdoc/html/render/print_item.rs3184
-rw-r--r--src/librustdoc/html/render/type_layout.rs6
-rw-r--r--src/librustdoc/html/render/write_shared.rs38
-rw-r--r--src/librustdoc/html/sources.rs2
-rw-r--r--src/librustdoc/html/static/js/rustdoc.d.ts17
-rw-r--r--src/librustdoc/html/static/js/search.js69
-rw-r--r--src/librustdoc/lib.rs12
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs2
m---------src/llvm-project0
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils/mod.rs27
-rw-r--r--src/tools/clippy/clippy_utils/src/macros.rs3
-rw-r--r--src/tools/compiletest/src/common.rs3
-rw-r--r--src/tools/compiletest/src/directive-list.rs2
-rw-r--r--src/tools/compiletest/src/header.rs16
-rw-r--r--src/tools/compiletest/src/header/cfg.rs10
-rw-r--r--src/tools/compiletest/src/header/tests.rs9
-rw-r--r--src/tools/compiletest/src/lib.rs50
-rw-r--r--src/tools/compiletest/src/runtest.rs17
-rw-r--r--src/tools/compiletest/src/runtest/run_make.rs283
-rw-r--r--src/tools/jsondocck/src/main.rs43
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/tests/pass/unsized.rs15
-rw-r--r--src/tools/opt-dist/src/main.rs1
-rw-r--r--src/tools/opt-dist/src/metrics.rs73
-rw-r--r--src/tools/run-make-support/src/artifact_names.rs17
-rw-r--r--src/tools/run-make-support/src/external_deps/c_cxx_compiler/cc.rs11
-rw-r--r--src/tools/run-make-support/src/external_deps/c_cxx_compiler/extras.rs55
-rw-r--r--src/tools/run-make-support/src/external_deps/rustc.rs33
-rw-r--r--src/tools/run-make-support/src/external_deps/rustdoc.rs31
-rw-r--r--src/tools/run-make-support/src/lib.rs2
-rw-r--r--src/tools/run-make-support/src/run.rs19
-rw-r--r--src/tools/run-make-support/src/util.rs6
-rw-r--r--src/tools/rust-analyzer/.github/workflows/autopublish.yaml2
-rw-r--r--src/tools/rust-analyzer/.github/workflows/ci.yaml2
-rw-r--r--src/tools/rust-analyzer/.github/workflows/fuzz.yml2
-rw-r--r--src/tools/rust-analyzer/.github/workflows/publish-libs.yaml2
-rw-r--r--src/tools/rust-analyzer/.github/workflows/release.yaml59
-rw-r--r--src/tools/rust-analyzer/.typos.toml2
-rw-r--r--src/tools/rust-analyzer/Cargo.lock33
-rw-r--r--src/tools/rust-analyzer/Cargo.toml13
-rw-r--r--src/tools/rust-analyzer/crates/base-db/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/cfg/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/Cargo.toml1
-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/item_tree.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/resolver.rs5
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/builtin/attr_macro.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/files.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/lib.rs54
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs35
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/db.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/drop.rs209
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer.rs9
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout.rs47
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lib.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs11
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/target_feature.rs261
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/utils.rs37
-rw-r--r--src/tools/rust-analyzer/crates/hir/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs84
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics.rs19
-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/term_search/expr.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs22
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_match_arms.rs49
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs123
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs80
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_while_to_loop.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_comma.rs53
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_or_pattern.rs80
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_trait_bound.rs9
-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/generate_impl.rs26
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs23
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs47
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_type_alias.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/invert_if.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_mut.rs15
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs19
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_param.rs62
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs22
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs19
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/utils.rs78
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/item.rs14
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/render.rs28
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs34
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/lib.rs6
-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.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/source_change.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/suggest_name.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_unsafe.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/ide/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/doc_links.rs19
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs92
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/render.rs95
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/tests.rs594
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/inlay_hints/adjustment.rs23
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/moniker.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/static_index.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs343
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/escape.rs21
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/highlight.rs20
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/macro_.rs128
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html20
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html18
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html8
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html10
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_issue_18089.html4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html16
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html16
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html16
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html16
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_macros.html50
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html18
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html116
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html8
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs27
-rw-r--r--src/tools/rust-analyzer/crates/intern/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/mbe/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/parser.rs4
-rw-r--r--src/tools/rust-analyzer/crates/parser/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/input.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/output.rs5
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/syntax_kind/generated.rs19
-rw-r--r--src/tools/rust-analyzer/crates/paths/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/paths/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/profile/Cargo.toml3
-rw-r--r--src/tools/rust-analyzer/crates/profile/src/stop_watch.rs10
-rw-r--r--src/tools/rust-analyzer/crates/project-model/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs4
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/project_json.rs12
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/sysroot.rs147
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/tests.rs14
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/workspace.rs238
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/is-proc-macro-project.json13
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_cfg_groups.txt501
-rw-r--r--src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt454
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml3
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs3
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs6
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs21
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/op_queue.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/config.rs4
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/hprof.rs3
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/json.rs3
-rw-r--r--src/tools/rust-analyzer/crates/stdx/Cargo.toml4
-rw-r--r--src/tools/rust-analyzer/crates/stdx/src/anymap.rs3
-rw-r--r--src/tools/rust-analyzer/crates/stdx/src/assert.rs115
-rw-r--r--src/tools/rust-analyzer/crates/stdx/src/lib.rs5
-rw-r--r--src/tools/rust-analyzer/crates/stdx/src/macros.rs2
-rw-r--r--src/tools/rust-analyzer/crates/syntax-bridge/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/syntax/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/syntax/rust.ungram6
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/algo.rs26
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/edit.rs4
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/make.rs2
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/prec.rs49
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory.rs5
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory/constructors.rs288
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/token_ext.rs4
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs59
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs111
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs6
-rw-r--r--src/tools/rust-analyzer/crates/test-utils/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/test-utils/src/assert_linear.rs2
-rw-r--r--src/tools/rust-analyzer/crates/test-utils/src/fixture.rs24
-rw-r--r--src/tools/rust-analyzer/crates/test-utils/src/lib.rs4
-rw-r--r--src/tools/rust-analyzer/crates/toolchain/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/tt/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/vfs/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/vfs/src/anchored_path.rs2
-rw-r--r--src/tools/rust-analyzer/crates/vfs/src/vfs_path.rs2
-rw-r--r--src/tools/rust-analyzer/docs/book/src/assists_generated.md38
-rw-r--r--src/tools/rust-analyzer/docs/book/src/configuration_generated.md5
-rw-r--r--src/tools/rust-analyzer/docs/book/src/contributing/setup.md14
-rw-r--r--src/tools/rust-analyzer/editors/code/.eslintignore2
-rw-r--r--src/tools/rust-analyzer/editors/code/.eslintrc.js46
-rw-r--r--src/tools/rust-analyzer/editors/code/.prettierrc.js5
-rw-r--r--src/tools/rust-analyzer/editors/code/eslint.config.mts48
-rw-r--r--src/tools/rust-analyzer/editors/code/package-lock.json3458
-rw-r--r--src/tools/rust-analyzer/editors/code/package.json61
-rw-r--r--src/tools/rust-analyzer/editors/code/prettier.config.mts12
-rw-r--r--src/tools/rust-analyzer/editors/code/src/bootstrap.ts4
-rw-r--r--src/tools/rust-analyzer/editors/code/src/client.ts507
-rw-r--r--src/tools/rust-analyzer/editors/code/src/commands.ts12
-rw-r--r--src/tools/rust-analyzer/editors/code/src/config.ts28
-rw-r--r--src/tools/rust-analyzer/editors/code/src/ctx.ts41
-rw-r--r--src/tools/rust-analyzer/editors/code/src/debug.ts9
-rw-r--r--src/tools/rust-analyzer/editors/code/src/diagnostics.ts44
-rw-r--r--src/tools/rust-analyzer/editors/code/src/lang_client.ts2
-rw-r--r--src/tools/rust-analyzer/editors/code/src/lsp_ext.ts1
-rw-r--r--src/tools/rust-analyzer/editors/code/src/main.ts1
-rw-r--r--src/tools/rust-analyzer/editors/code/src/persistent_state.ts1
-rw-r--r--src/tools/rust-analyzer/editors/code/src/snippets.ts4
-rw-r--r--src/tools/rust-analyzer/editors/code/src/syntax_tree_provider.ts2
-rw-r--r--src/tools/rust-analyzer/editors/code/src/test_explorer.ts2
-rw-r--r--src/tools/rust-analyzer/editors/code/src/toolchain.ts20
-rw-r--r--src/tools/rust-analyzer/editors/code/src/util.ts18
-rw-r--r--src/tools/rust-analyzer/editors/code/tests/unit/index.ts3
-rw-r--r--src/tools/rust-analyzer/editors/code/tests/unit/tasks.test.ts5
-rw-r--r--src/tools/rust-analyzer/editors/code/tsconfig.eslint.json2
-rw-r--r--src/tools/rust-analyzer/editors/code/tsconfig.json11
-rw-r--r--src/tools/rust-analyzer/rust-version2
-rw-r--r--src/tools/rust-analyzer/xtask/src/dist.rs29
-rw-r--r--src/tools/rust-analyzer/xtask/src/flags.rs3
-rw-r--r--src/tools/rust-analyzer/xtask/src/release.rs2
-rw-r--r--src/tools/rustdoc/Cargo.toml2
-rw-r--r--src/tools/rustfmt/src/macros.rs34
-rw-r--r--src/tools/rustfmt/src/spanned.rs7
-rw-r--r--src/tools/rustfmt/src/types.rs35
-rw-r--r--src/tools/rustfmt/tests/target/cfg_attribute_in_where.rs116
-rw-r--r--src/tools/tidy/src/allowed_run_make_makefiles.txt0
-rw-r--r--src/tools/tidy/src/lib.rs1
-rw-r--r--src/tools/tidy/src/main.rs2
-rw-r--r--src/tools/tidy/src/run_make_tests.rs104
-rw-r--r--src/tools/tidy/src/style.rs21
315 files changed, 11405 insertions, 13371 deletions
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index e3f58d97cbc..c3b25646439 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -292,7 +292,7 @@ v(
 v("release-channel", "rust.channel", "the name of the release channel to build")
 v(
     "release-description",
-    "rust.description",
+    "build.description",
     "optional descriptive string for version output",
 )
 v("dist-compression-formats", None, "List of compression formats to use")
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index d645d922ef4..78219500737 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -994,7 +994,9 @@ impl Step for Rustc {
     fn make_run(run: RunConfig<'_>) {
         let crates = run.cargo_crates_in_set();
         run.builder.ensure(Rustc {
-            compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
+            compiler: run
+                .builder
+                .compiler(run.builder.top_stage.saturating_sub(1), run.build_triple()),
             target: run.target,
             crates,
         });
@@ -1911,7 +1913,7 @@ impl Step for Assemble {
 
     fn make_run(run: RunConfig<'_>) {
         run.builder.ensure(Assemble {
-            target_compiler: run.builder.compiler(run.builder.top_stage + 1, run.target),
+            target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
         });
     }
 
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 26b3e0b701c..e0ad6856dc7 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -2464,3 +2464,30 @@ impl Step for ReproducibleArtifacts {
         if added_anything { Some(tarball.generate()) } else { None }
     }
 }
+
+/// Tarball containing a prebuilt version of the libgccjit library,
+/// needed as a dependency for the GCC codegen backend (similarly to the LLVM
+/// backend needing a prebuilt libLLVM).
+#[derive(Clone, Debug, Eq, Hash, PartialEq)]
+pub struct Gcc {
+    pub target: TargetSelection,
+}
+
+impl Step for Gcc {
+    type Output = GeneratedTarball;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.alias("gcc")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(Gcc { target: run.target });
+    }
+
+    fn run(self, builder: &Builder<'_>) -> Self::Output {
+        let tarball = Tarball::new(builder, "gcc", &self.target.triple);
+        let output = builder.ensure(super::gcc::Gcc { target: self.target });
+        tarball.add_file(output.libgccjit, ".", 0o644);
+        tarball.generate()
+    }
+}
diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs
index f25dfaab0f1..ae6544227a6 100644
--- a/src/bootstrap/src/core/build_steps/setup.rs
+++ b/src/bootstrap/src/core/build_steps/setup.rs
@@ -216,8 +216,9 @@ fn setup_config_toml(path: &Path, profile: Profile, config: &Config) {
 
     let latest_change_id = CONFIG_CHANGE_HISTORY.last().unwrap().change_id;
     let settings = format!(
-        "# Includes one of the default files in {PROFILE_DIR}\n\
-    profile = \"{profile}\"\n\
+        "# See bootstrap.example.toml for documentation of available options\n\
+    #\n\
+    profile = \"{profile}\"  # Includes one of the default files in {PROFILE_DIR}\n\
     change-id = {latest_change_id}\n"
     );
 
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index c9fa2e9ba96..4b7c8d5770e 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -90,7 +90,7 @@ impl Step for CrateBootstrap {
         );
 
         let crate_name = path.rsplit_once('/').unwrap().1;
-        run_cargo_test(cargo, &[], &[], crate_name, crate_name, bootstrap_host, builder);
+        run_cargo_test(cargo, &[], &[], crate_name, bootstrap_host, builder);
     }
 }
 
@@ -140,15 +140,7 @@ You can skip linkcheck with --skip src/tools/linkchecker"
             SourceType::InTree,
             &[],
         );
-        run_cargo_test(
-            cargo,
-            &[],
-            &[],
-            "linkchecker",
-            "linkchecker self tests",
-            bootstrap_host,
-            builder,
-        );
+        run_cargo_test(cargo, &[], &[], "linkchecker self tests", bootstrap_host, builder);
 
         if builder.doc_tests == DocTests::No {
             return;
@@ -337,7 +329,7 @@ impl Step for Cargo {
         );
 
         // NOTE: can't use `run_cargo_test` because we need to overwrite `PATH`
-        let mut cargo = prepare_cargo_test(cargo, &[], &[], "cargo", self.host, builder);
+        let mut cargo = prepare_cargo_test(cargo, &[], &[], self.host, builder);
 
         // Don't run cross-compile tests, we may not have cross-compiled libstd libs
         // available.
@@ -423,7 +415,7 @@ impl Step for RustAnalyzer {
         cargo.env("SKIP_SLOW_TESTS", "1");
 
         cargo.add_rustc_lib_path(builder);
-        run_cargo_test(cargo, &[], &[], "rust-analyzer", "rust-analyzer", host, builder);
+        run_cargo_test(cargo, &[], &[], "rust-analyzer", host, builder);
     }
 }
 
@@ -472,7 +464,7 @@ impl Step for Rustfmt {
 
         cargo.add_rustc_lib_path(builder);
 
-        run_cargo_test(cargo, &[], &[], "rustfmt", "rustfmt", host, builder);
+        run_cargo_test(cargo, &[], &[], "rustfmt", host, builder);
     }
 }
 
@@ -588,7 +580,7 @@ impl Step for Miri {
 
         // We can NOT use `run_cargo_test` since Miri's integration tests do not use the usual test
         // harness and therefore do not understand the flags added by `add_flags_and_try_run_test`.
-        let mut cargo = prepare_cargo_test(cargo, &[], &[], "miri", host, builder);
+        let mut cargo = prepare_cargo_test(cargo, &[], &[], host, builder);
 
         // miri tests need to know about the stage sysroot
         cargo.env("MIRI_SYSROOT", &miri_sysroot);
@@ -736,7 +728,7 @@ impl Step for CompiletestTest {
             &[],
         );
         cargo.allow_features("test");
-        run_cargo_test(cargo, &[], &[], "compiletest", "compiletest self test", host, builder);
+        run_cargo_test(cargo, &[], &[], "compiletest self test", host, builder);
     }
 }
 
@@ -797,7 +789,7 @@ impl Step for Clippy {
         cargo.env("HOST_LIBS", host_libs);
 
         cargo.add_rustc_lib_path(builder);
-        let cargo = prepare_cargo_test(cargo, &[], &[], "clippy", host, builder);
+        let cargo = prepare_cargo_test(cargo, &[], &[], host, builder);
 
         let _guard = builder.msg_sysroot_tool(Kind::Test, compiler.stage, "clippy", host, host);
 
@@ -1242,59 +1234,6 @@ macro_rules! test {
     };
 }
 
-#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
-pub struct RunMakeSupport {
-    pub compiler: Compiler,
-    pub target: TargetSelection,
-}
-
-impl Step for RunMakeSupport {
-    type Output = PathBuf;
-    const DEFAULT: bool = true;
-
-    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.never()
-    }
-
-    fn make_run(run: RunConfig<'_>) {
-        let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
-        run.builder.ensure(RunMakeSupport { compiler, target: run.build_triple() });
-    }
-
-    /// Builds run-make-support and returns the path to the resulting rlib.
-    fn run(self, builder: &Builder<'_>) -> PathBuf {
-        builder.ensure(compile::Std::new(self.compiler, self.target));
-
-        let cargo = tool::prepare_tool_cargo(
-            builder,
-            self.compiler,
-            Mode::ToolStd,
-            self.target,
-            Kind::Build,
-            "src/tools/run-make-support",
-            SourceType::InTree,
-            &[],
-        );
-
-        let _guard = builder.msg_tool(
-            Kind::Build,
-            Mode::ToolStd,
-            "run-make-support",
-            self.compiler.stage,
-            &self.compiler.host,
-            &self.target,
-        );
-        cargo.into_cmd().run(builder);
-
-        let lib_name = "librun_make_support.rlib";
-        let lib = builder.tools_dir(self.compiler).join(lib_name);
-
-        let cargo_out = builder.cargo_out(self.compiler, Mode::ToolStd, self.target).join(lib_name);
-        builder.copy_link(&cargo_out, &lib);
-        lib
-    }
-}
-
 /// Runs `cargo test` on the `src/tools/run-make-support` crate.
 /// That crate is used by run-make tests.
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -1330,15 +1269,7 @@ impl Step for CrateRunMakeSupport {
             &[],
         );
         cargo.allow_features("test");
-        run_cargo_test(
-            cargo,
-            &[],
-            &[],
-            "run-make-support",
-            "run-make-support self test",
-            host,
-            builder,
-        );
+        run_cargo_test(cargo, &[], &[], "run-make-support self test", host, builder);
     }
 }
 
@@ -1375,7 +1306,7 @@ impl Step for CrateBuildHelper {
             &[],
         );
         cargo.allow_features("test");
-        run_cargo_test(cargo, &[], &[], "build_helper", "build_helper self test", host, builder);
+        run_cargo_test(cargo, &[], &[], "build_helper self test", host, builder);
     }
 }
 
@@ -1446,40 +1377,7 @@ test!(Pretty {
     only_hosts: true,
 });
 
-/// Special-handling is needed for `run-make`, so don't use `test!` for defining `RunMake`
-/// tests.
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub struct RunMake {
-    pub compiler: Compiler,
-    pub target: TargetSelection,
-}
-
-impl Step for RunMake {
-    type Output = ();
-    const DEFAULT: bool = true;
-    const ONLY_HOSTS: bool = false;
-
-    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.suite_path("tests/run-make")
-    }
-
-    fn make_run(run: RunConfig<'_>) {
-        let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
-        run.builder.ensure(RunMakeSupport { compiler, target: run.build_triple() });
-        run.builder.ensure(RunMake { compiler, target: run.target });
-    }
-
-    fn run(self, builder: &Builder<'_>) {
-        builder.ensure(Compiletest {
-            compiler: self.compiler,
-            target: self.target,
-            mode: "run-make",
-            suite: "run-make",
-            path: "tests/run-make",
-            compare_mode: None,
-        });
-    }
-}
+test!(RunMake { path: "tests/run-make", mode: "run-make", suite: "run-make", default: true });
 
 test!(Assembly { path: "tests/assembly", mode: "assembly", suite: "assembly", default: true });
 
@@ -1722,6 +1620,9 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
                 host: target,
             });
         }
+        if suite == "run-make" {
+            builder.tool_exe(Tool::RunMakeSupport);
+        }
 
         // Also provide `rust_test_helpers` for the host.
         builder.ensure(TestHelpers { target: compiler.host });
@@ -1774,6 +1675,11 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
             };
 
             cmd.arg("--cargo-path").arg(cargo_path);
+
+            // We need to pass the compiler that was used to compile run-make-support,
+            // because we have to use the same compiler to compile rmake.rs recipes.
+            let stage0_rustc_path = builder.compiler(0, compiler.host);
+            cmd.arg("--stage0-rustc-path").arg(builder.rustc(stage0_rustc_path));
         }
 
         // Avoid depending on rustdoc when we don't need it.
@@ -2585,13 +2491,12 @@ fn run_cargo_test<'a>(
     cargo: builder::Cargo,
     libtest_args: &[&str],
     crates: &[String],
-    primary_crate: &str,
     description: impl Into<Option<&'a str>>,
     target: TargetSelection,
     builder: &Builder<'_>,
 ) -> bool {
     let compiler = cargo.compiler();
-    let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, primary_crate, target, builder);
+    let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, target, builder);
     let _time = helpers::timeit(builder);
     let _group = description.into().and_then(|what| {
         builder.msg_sysroot_tool(Kind::Test, compiler.stage, what, compiler.host, target)
@@ -2615,7 +2520,6 @@ fn prepare_cargo_test(
     cargo: builder::Cargo,
     libtest_args: &[&str],
     crates: &[String],
-    primary_crate: &str,
     target: TargetSelection,
     builder: &Builder<'_>,
 ) -> BootstrapCommand {
@@ -2645,13 +2549,6 @@ fn prepare_cargo_test(
             cargo.arg("--doc");
         }
         DocTests::No => {
-            let krate = &builder
-                .crates
-                .get(primary_crate)
-                .unwrap_or_else(|| panic!("missing crate {primary_crate}"));
-            if krate.has_lib {
-                cargo.arg("--lib");
-            }
             cargo.args(["--bins", "--examples", "--tests", "--benches"]);
         }
         DocTests::Yes => {}
@@ -2826,15 +2723,15 @@ impl Step for Crate {
             _ => panic!("can only test libraries"),
         };
 
-        run_cargo_test(
-            cargo,
-            &[],
-            &self.crates,
-            &self.crates[0],
-            &*crate_description(&self.crates),
-            target,
-            builder,
-        );
+        let mut crates = self.crates.clone();
+        // The core crate can't directly be tested. We could silently
+        // ignore it, but adding it's own test crate is less confusing
+        // for users. We still keep core itself for doctests.
+        if crates.iter().any(|crate_| crate_ == "core") {
+            crates.push("coretests".to_owned());
+        }
+
+        run_cargo_test(cargo, &[], &crates, &*crate_description(&self.crates), target, builder);
     }
 }
 
@@ -2927,15 +2824,7 @@ impl Step for CrateRustdoc {
         dylib_path.insert(0, PathBuf::from(&*libdir));
         cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
 
-        run_cargo_test(
-            cargo,
-            &[],
-            &["rustdoc:0.0.0".to_string()],
-            "rustdoc",
-            "rustdoc",
-            target,
-            builder,
-        );
+        run_cargo_test(cargo, &[], &["rustdoc:0.0.0".to_string()], "rustdoc", target, builder);
     }
 }
 
@@ -2992,7 +2881,6 @@ impl Step for CrateRustdocJsonTypes {
             libtest_args,
             &["rustdoc-json-types".to_string()],
             "rustdoc-json-types",
-            "rustdoc-json-types",
             target,
             builder,
         );
@@ -3172,7 +3060,7 @@ impl Step for Bootstrap {
 
         // bootstrap tests are racy on directory creation so just run them one at a time.
         // Since there's not many this shouldn't be a problem.
-        run_cargo_test(cargo, &["--test-threads=1"], &[], "bootstrap", None, host, builder);
+        run_cargo_test(cargo, &["--test-threads=1"], &[], None, host, builder);
     }
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -3297,7 +3185,7 @@ impl Step for RustInstaller {
             bootstrap_host,
             bootstrap_host,
         );
-        run_cargo_test(cargo, &[], &[], "installer", None, bootstrap_host, builder);
+        run_cargo_test(cargo, &[], &[], None, bootstrap_host, builder);
 
         // We currently don't support running the test.sh script outside linux(?) environments.
         // Eventually this should likely migrate to #[test]s in rust-installer proper rather than a
@@ -3688,7 +3576,7 @@ impl Step for TestFloatParse {
             &[],
         );
 
-        run_cargo_test(cargo_test, &[], &[], crate_name, crate_name, bootstrap_host, builder);
+        run_cargo_test(cargo_test, &[], &[], crate_name, bootstrap_host, builder);
 
         // Run the actual parse tests.
         let mut cargo_run = tool::prepare_tool_cargo(
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 39acb646dff..6a9e373fbc9 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -35,6 +35,12 @@ pub enum SourceType {
 }
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
+pub enum ToolArtifactKind {
+    Binary,
+    Library,
+}
+
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
 struct ToolBuild {
     compiler: Compiler,
     target: TargetSelection,
@@ -47,6 +53,8 @@ struct ToolBuild {
     allow_features: &'static str,
     /// Additional arguments to pass to the `cargo` invocation.
     cargo_args: Vec<String>,
+    /// Whether the tool builds a binary or a library.
+    artifact_kind: ToolArtifactKind,
 }
 
 impl Builder<'_> {
@@ -79,7 +87,7 @@ impl Builder<'_> {
 /// for using this type as `type Output = ToolBuildResult;`
 #[derive(Clone)]
 pub struct ToolBuildResult {
-    /// Executable path of the corresponding tool that was built.
+    /// Artifact path of the corresponding tool that was built.
     pub tool_path: PathBuf,
     /// Compiler used to build the tool. For non-`ToolRustc` tools this is equal to `target_compiler`.
     /// For `ToolRustc` this is one stage before of the `target_compiler`.
@@ -179,8 +187,14 @@ impl Step for ToolBuild {
             if tool == "tidy" {
                 tool = "rust-tidy";
             }
-            let tool_path =
-                copy_link_tool_bin(builder, self.compiler, self.target, self.mode, tool);
+            let tool_path = match self.artifact_kind {
+                ToolArtifactKind::Binary => {
+                    copy_link_tool_bin(builder, self.compiler, self.target, self.mode, tool)
+                }
+                ToolArtifactKind::Library => builder
+                    .cargo_out(self.compiler, self.mode, self.target)
+                    .join(format!("lib{tool}.rlib")),
+            };
 
             ToolBuildResult { tool_path, build_compiler: self.compiler, target_compiler }
         }
@@ -234,23 +248,32 @@ pub fn prepare_tool_cargo(
     cargo.env("CFG_VERSION", builder.rust_version());
     cargo.env("CFG_RELEASE_NUM", &builder.version);
     cargo.env("DOC_RUST_LANG_ORG_CHANNEL", builder.doc_rust_lang_org_channel());
+
     if let Some(ref ver_date) = builder.rust_info().commit_date() {
         cargo.env("CFG_VER_DATE", ver_date);
     }
+
     if let Some(ref ver_hash) = builder.rust_info().sha() {
         cargo.env("CFG_VER_HASH", ver_hash);
     }
 
+    if let Some(description) = &builder.config.description {
+        cargo.env("CFG_VER_DESCRIPTION", description);
+    }
+
     let info = GitInfo::new(builder.config.omit_git_hash, &dir);
     if let Some(sha) = info.sha() {
         cargo.env("CFG_COMMIT_HASH", sha);
     }
+
     if let Some(sha_short) = info.sha_short() {
         cargo.env("CFG_SHORT_COMMIT_HASH", sha_short);
     }
+
     if let Some(date) = info.commit_date() {
         cargo.env("CFG_COMMIT_DATE", date);
     }
+
     if !features.is_empty() {
         cargo.arg("--features").arg(features.join(", "));
     }
@@ -330,6 +353,7 @@ macro_rules! bootstrap_tool {
         $(,is_unstable_tool = $unstable:expr)*
         $(,allow_features = $allow_features:expr)?
         $(,submodules = $submodules:expr)?
+        $(,artifact_kind = $artifact_kind:expr)?
         ;
     )+) => {
         #[derive(PartialEq, Eq, Clone)]
@@ -389,6 +413,7 @@ macro_rules! bootstrap_tool {
                         builder.require_submodule(submodule, None);
                     }
                 )*
+
                 builder.ensure(ToolBuild {
                     compiler: self.compiler,
                     target: self.target,
@@ -407,7 +432,12 @@ macro_rules! bootstrap_tool {
                     },
                     extra_features: vec![],
                     allow_features: concat!($($allow_features)*),
-                    cargo_args: vec![]
+                    cargo_args: vec![],
+                    artifact_kind: if false $(|| $artifact_kind == ToolArtifactKind::Library)* {
+                        ToolArtifactKind::Library
+                    } else {
+                        ToolArtifactKind::Binary
+                    }
                 })
             }
         }
@@ -445,51 +475,14 @@ bootstrap_tool!(
     WasmComponentLd, "src/tools/wasm-component-ld", "wasm-component-ld", is_unstable_tool = true, allow_features = "min_specialization";
     UnicodeTableGenerator, "src/tools/unicode-table-generator", "unicode-table-generator";
     FeaturesStatusDump, "src/tools/features-status-dump", "features-status-dump";
+    OptimizedDist, "src/tools/opt-dist", "opt-dist", submodules = &["src/tools/rustc-perf"];
+    RunMakeSupport, "src/tools/run-make-support", "run_make_support", artifact_kind = ToolArtifactKind::Library;
 );
 
 /// These are the submodules that are required for rustbook to work due to
 /// depending on mdbook plugins.
 pub static SUBMODULES_FOR_RUSTBOOK: &[&str] = &["src/doc/book", "src/doc/reference"];
 
-#[derive(Debug, Clone, Hash, PartialEq, Eq)]
-pub struct OptimizedDist {
-    pub compiler: Compiler,
-    pub target: TargetSelection,
-}
-
-impl Step for OptimizedDist {
-    type Output = ToolBuildResult;
-
-    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("src/tools/opt-dist")
-    }
-
-    fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(OptimizedDist {
-            compiler: run.builder.compiler(0, run.builder.config.build),
-            target: run.target,
-        });
-    }
-
-    fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
-        // We need to ensure the rustc-perf submodule is initialized when building opt-dist since
-        // the tool requires it to be in place to run.
-        builder.require_submodule("src/tools/rustc-perf", None);
-
-        builder.ensure(ToolBuild {
-            compiler: self.compiler,
-            target: self.target,
-            tool: "opt-dist",
-            mode: Mode::ToolBootstrap,
-            path: "src/tools/opt-dist",
-            source_type: SourceType::InTree,
-            extra_features: Vec::new(),
-            allow_features: "",
-            cargo_args: Vec::new(),
-        })
-    }
-}
-
 /// The [rustc-perf](https://github.com/rust-lang/rustc-perf) benchmark suite, which is added
 /// as a submodule at `src/tools/rustc-perf`.
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
@@ -529,6 +522,7 @@ impl Step for RustcPerf {
             // Only build the collector package, which is used for benchmarking through
             // a CLI.
             cargo_args: vec!["-p".to_string(), "collector".to_string()],
+            artifact_kind: ToolArtifactKind::Binary,
         };
         let res = builder.ensure(tool.clone());
         // We also need to symlink the `rustc-fake` binary to the corresponding directory,
@@ -586,6 +580,7 @@ impl Step for ErrorIndex {
             extra_features: Vec::new(),
             allow_features: "",
             cargo_args: Vec::new(),
+            artifact_kind: ToolArtifactKind::Binary,
         })
     }
 }
@@ -621,6 +616,7 @@ impl Step for RemoteTestServer {
             extra_features: Vec::new(),
             allow_features: "",
             cargo_args: Vec::new(),
+            artifact_kind: ToolArtifactKind::Binary,
         })
     }
 }
@@ -725,6 +721,7 @@ impl Step for Rustdoc {
                 extra_features,
                 allow_features: "",
                 cargo_args: Vec::new(),
+                artifact_kind: ToolArtifactKind::Binary,
             });
 
         // don't create a stage0-sysroot/bin directory.
@@ -779,6 +776,7 @@ impl Step for Cargo {
             extra_features: Vec::new(),
             allow_features: "",
             cargo_args: Vec::new(),
+            artifact_kind: ToolArtifactKind::Binary,
         })
     }
 }
@@ -827,6 +825,7 @@ impl Step for LldWrapper {
             extra_features: Vec::new(),
             allow_features: "",
             cargo_args: Vec::new(),
+            artifact_kind: ToolArtifactKind::Binary,
         });
 
         let libdir_bin = builder.sysroot_target_bindir(self.target_compiler, target);
@@ -887,6 +886,7 @@ impl Step for RustAnalyzer {
             source_type: SourceType::InTree,
             allow_features: RustAnalyzer::ALLOW_FEATURES,
             cargo_args: Vec::new(),
+            artifact_kind: ToolArtifactKind::Binary,
         })
     }
 }
@@ -931,6 +931,7 @@ impl Step for RustAnalyzerProcMacroSrv {
             source_type: SourceType::InTree,
             allow_features: RustAnalyzer::ALLOW_FEATURES,
             cargo_args: Vec::new(),
+            artifact_kind: ToolArtifactKind::Binary,
         });
 
         // Copy `rust-analyzer-proc-macro-srv` to `<sysroot>/libexec/`
@@ -985,6 +986,7 @@ impl Step for LlvmBitcodeLinker {
             extra_features: self.extra_features,
             allow_features: "",
             cargo_args: Vec::new(),
+            artifact_kind: ToolArtifactKind::Binary,
         });
 
         if tool_result.target_compiler.stage > 0 {
@@ -1164,6 +1166,7 @@ fn run_tool_build_step(
             source_type: SourceType::InTree,
             allow_features: "",
             cargo_args: vec![],
+            artifact_kind: ToolArtifactKind::Binary,
         });
 
     // FIXME: This should just be an if-let-chain, but those are unstable.
@@ -1242,6 +1245,7 @@ impl Step for TestFloatParse {
             extra_features: Vec::new(),
             allow_features: "",
             cargo_args: Vec::new(),
+            artifact_kind: ToolArtifactKind::Binary,
         })
     }
 }
diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs
index c8e2856bdc8..7d404a4f7ff 100644
--- a/src/bootstrap/src/core/builder/mod.rs
+++ b/src/bootstrap/src/core/builder/mod.rs
@@ -1072,6 +1072,7 @@ impl<'a> Builder<'a> {
                 dist::PlainSourceTarball,
                 dist::BuildManifest,
                 dist::ReproducibleArtifacts,
+                dist::Gcc
             ),
             Kind::Install => describe!(
                 install::Docs,
diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index 0eaa89792bd..1f27002f81c 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -653,6 +653,20 @@ mod dist {
             &["compiler/rustc".into(), "library".into()],
         );
 
+        assert_eq!(builder.config.stage, 2);
+
+        // `compile::Rustc` includes one-stage-off compiler information as the target compiler
+        // artifacts get copied from there to the target stage sysroot.
+        // For example, `stage2/bin/rustc` gets copied from the `stage1-rustc` build directory.
+        assert_eq!(
+            first(builder.cache.all::<compile::Rustc>()),
+            &[
+                rustc!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 0),
+                rustc!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 1),
+                rustc!(TEST_TRIPLE_1 => TEST_TRIPLE_2, stage = 1),
+            ]
+        );
+
         assert_eq!(
             first(builder.cache.all::<compile::Std>()),
             &[
@@ -664,15 +678,34 @@ mod dist {
                 std!(TEST_TRIPLE_1 => TEST_TRIPLE_3, stage = 2),
             ]
         );
-        assert_eq!(builder.cache.all::<compile::Assemble>().len(), 5);
+
         assert_eq!(
-            first(builder.cache.all::<compile::Rustc>()),
+            first(builder.cache.all::<compile::Assemble>()),
             &[
-                rustc!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 0),
-                rustc!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 1),
-                rustc!(TEST_TRIPLE_1 => TEST_TRIPLE_1, stage = 2),
-                rustc!(TEST_TRIPLE_1 => TEST_TRIPLE_2, stage = 1),
-                rustc!(TEST_TRIPLE_1 => TEST_TRIPLE_2, stage = 2),
+                compile::Assemble {
+                    target_compiler: Compiler {
+                        host: TargetSelection::from_user(TEST_TRIPLE_1),
+                        stage: 0
+                    }
+                },
+                compile::Assemble {
+                    target_compiler: Compiler {
+                        host: TargetSelection::from_user(TEST_TRIPLE_1),
+                        stage: 1
+                    }
+                },
+                compile::Assemble {
+                    target_compiler: Compiler {
+                        host: TargetSelection::from_user(TEST_TRIPLE_1),
+                        stage: 2
+                    }
+                },
+                compile::Assemble {
+                    target_compiler: Compiler {
+                        host: TargetSelection::from_user(TEST_TRIPLE_2),
+                        stage: 2
+                    }
+                },
             ]
         );
     }
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index d0e0ed50ad8..ac24da9f86b 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -894,6 +894,7 @@ define_config! {
     #[derive(Default)]
     struct Build {
         build: Option<String> = "build",
+        description: Option<String> = "description",
         host: Option<Vec<String>> = "host",
         target: Option<Vec<String>> = "target",
         build_dir: Option<String> = "build-dir",
@@ -1176,6 +1177,7 @@ define_config! {
         incremental: Option<bool> = "incremental",
         default_linker: Option<String> = "default-linker",
         channel: Option<String> = "channel",
+        // FIXME: Remove this field at Q2 2025, it has been replaced by build.description
         description: Option<String> = "description",
         musl_root: Option<String> = "musl-root",
         rpath: Option<bool> = "rpath",
@@ -1583,6 +1585,7 @@ impl Config {
         config.change_id = toml.change_id.inner;
 
         let Build {
+            mut description,
             build,
             host,
             target,
@@ -1831,7 +1834,7 @@ impl Config {
                 randomize_layout,
                 default_linker,
                 channel: _, // already handled above
-                description,
+                description: rust_description,
                 musl_root,
                 rpath,
                 verbose_tests,
@@ -1924,7 +1927,12 @@ impl Config {
             set(&mut config.jemalloc, jemalloc);
             set(&mut config.test_compare_mode, test_compare_mode);
             set(&mut config.backtrace, backtrace);
-            config.description = description;
+            if rust_description.is_some() {
+                eprintln!(
+                    "Warning: rust.description is deprecated. Use build.description instead."
+                );
+            }
+            description = description.or(rust_description);
             set(&mut config.rust_dist_src, dist_src);
             set(&mut config.verbose_tests, verbose_tests);
             // in the case "false" is set explicitly, do not overwrite the command line args
@@ -1990,6 +1998,7 @@ impl Config {
         }
 
         config.reproducible_artifacts = flags.reproducible_artifact;
+        config.description = description;
 
         // We need to override `rust.channel` if it's manually specified when using the CI rustc.
         // This is because if the compiler uses a different channel than the one specified in config.toml,
diff --git a/src/bootstrap/src/core/metadata.rs b/src/bootstrap/src/core/metadata.rs
index 01cbf662940..2706aba5ffc 100644
--- a/src/bootstrap/src/core/metadata.rs
+++ b/src/bootstrap/src/core/metadata.rs
@@ -28,7 +28,6 @@ struct Package {
     source: Option<String>,
     manifest_path: String,
     dependencies: Vec<Dependency>,
-    targets: Vec<Target>,
     features: BTreeMap<String, Vec<String>>,
 }
 
@@ -40,11 +39,6 @@ struct Dependency {
     source: Option<String>,
 }
 
-#[derive(Debug, Deserialize)]
-struct Target {
-    kind: Vec<String>,
-}
-
 /// Collects and stores package metadata of each workspace members into `build`,
 /// by executing `cargo metadata` commands.
 pub fn build(build: &mut Build) {
@@ -59,12 +53,10 @@ pub fn build(build: &mut Build) {
                 .filter(|dep| dep.source.is_none())
                 .map(|dep| dep.name)
                 .collect();
-            let has_lib = package.targets.iter().any(|t| t.kind.iter().any(|k| k == "lib"));
             let krate = Crate {
                 name: name.clone(),
                 deps,
                 path,
-                has_lib,
                 features: package.features.keys().cloned().collect(),
             };
             let relative_path = krate.local_path(build);
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 351e67f6702..4ea711c1325 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -185,7 +185,6 @@ struct Crate {
     name: String,
     deps: HashSet<String>,
     path: PathBuf,
-    has_lib: bool,
     features: Vec<String>,
 }
 
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index 5f49c50c5ad..425ffdccad5 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -365,4 +365,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Info,
         summary: "`rust.channel` now supports \"auto-detect\" to load the channel from `src/ci/channel`",
     },
+    ChangeInfo {
+        change_id: 137723,
+        severity: ChangeSeverity::Info,
+        summary: "The rust.description option has moved to build.description and rust.description is now deprecated.",
+    },
 ];
diff --git a/src/bootstrap/src/utils/metrics.rs b/src/bootstrap/src/utils/metrics.rs
index b51fd490535..57766fd63fb 100644
--- a/src/bootstrap/src/utils/metrics.rs
+++ b/src/bootstrap/src/utils/metrics.rs
@@ -200,6 +200,14 @@ impl BuildMetrics {
             }
         };
         invocations.push(JsonInvocation {
+            // The command-line invocation with which bootstrap was invoked.
+            // Skip the first argument, as it is a potentially long absolute
+            // path that is not interesting.
+            cmdline: std::env::args_os()
+                .skip(1)
+                .map(|arg| arg.to_string_lossy().to_string())
+                .collect::<Vec<_>>()
+                .join(" "),
             start_time: state
                 .invocation_start
                 .duration_since(SystemTime::UNIX_EPOCH)
diff --git a/src/build_helper/src/metrics.rs b/src/build_helper/src/metrics.rs
index 538c33e9b15..eb306550fc4 100644
--- a/src/build_helper/src/metrics.rs
+++ b/src/build_helper/src/metrics.rs
@@ -1,3 +1,5 @@
+use std::time::Duration;
+
 use serde_derive::{Deserialize, Serialize};
 
 #[derive(Serialize, Deserialize)]
@@ -12,6 +14,8 @@ pub struct JsonRoot {
 #[derive(Serialize, Deserialize)]
 #[serde(rename_all = "snake_case")]
 pub struct JsonInvocation {
+    // Remembers the command-line invocation with which bootstrap was invoked.
+    pub cmdline: String,
     // Unix timestamp in seconds
     //
     // This is necessary to easily correlate this invocation with logs or other data.
@@ -98,3 +102,87 @@ fn null_as_f64_nan<'de, D: serde::Deserializer<'de>>(d: D) -> Result<f64, D::Err
     use serde::Deserialize as _;
     Option::<f64>::deserialize(d).map(|f| f.unwrap_or(f64::NAN))
 }
+
+/// Represents a single bootstrap step, with the accumulated duration of all its children.
+#[derive(Clone, Debug)]
+pub struct BuildStep {
+    pub r#type: String,
+    pub children: Vec<BuildStep>,
+    pub duration: Duration,
+}
+
+impl BuildStep {
+    /// Create a `BuildStep` representing a single invocation of bootstrap.
+    /// The most important thing is that the build step aggregates the
+    /// durations of all children, so that it can be easily accessed.
+    pub fn from_invocation(invocation: &JsonInvocation) -> Self {
+        fn parse(node: &JsonNode) -> Option<BuildStep> {
+            match node {
+                JsonNode::RustbuildStep {
+                    type_: kind,
+                    children,
+                    duration_excluding_children_sec,
+                    ..
+                } => {
+                    let children: Vec<_> = children.into_iter().filter_map(parse).collect();
+                    let children_duration = children.iter().map(|c| c.duration).sum::<Duration>();
+                    Some(BuildStep {
+                        r#type: kind.to_string(),
+                        children,
+                        duration: children_duration
+                            + Duration::from_secs_f64(*duration_excluding_children_sec),
+                    })
+                }
+                JsonNode::TestSuite(_) => None,
+            }
+        }
+
+        let duration = Duration::from_secs_f64(invocation.duration_including_children_sec);
+        let children: Vec<_> = invocation.children.iter().filter_map(parse).collect();
+        Self { r#type: "total".to_string(), children, duration }
+    }
+
+    pub fn find_all_by_type(&self, r#type: &str) -> Vec<&Self> {
+        let mut result = Vec::new();
+        self.find_by_type(r#type, &mut result);
+        result
+    }
+
+    fn find_by_type<'a>(&'a self, r#type: &str, result: &mut Vec<&'a Self>) {
+        if self.r#type == r#type {
+            result.push(self);
+        }
+        for child in &self.children {
+            child.find_by_type(r#type, result);
+        }
+    }
+}
+
+/// Writes build steps into a nice indented table.
+pub fn format_build_steps(root: &BuildStep) -> String {
+    use std::fmt::Write;
+
+    let mut substeps: Vec<(u32, &BuildStep)> = Vec::new();
+
+    fn visit<'a>(step: &'a BuildStep, level: u32, substeps: &mut Vec<(u32, &'a BuildStep)>) {
+        substeps.push((level, step));
+        for child in &step.children {
+            visit(child, level + 1, substeps);
+        }
+    }
+
+    visit(root, 0, &mut substeps);
+
+    let mut output = String::new();
+    for (level, step) in substeps {
+        let label = format!(
+            "{}{}",
+            ".".repeat(level as usize),
+            // Bootstrap steps can be generic and thus contain angle brackets (<...>).
+            // However, Markdown interprets these as HTML, so we need to escap ethem.
+            step.r#type.replace('<', "&lt;").replace('>', "&gt;")
+        );
+        writeln!(output, "{label:.<65}{:>8.2}s", step.duration.as_secs_f64()).unwrap();
+    }
+    output
+}
diff --git a/src/ci/citool/Cargo.lock b/src/ci/citool/Cargo.lock
new file mode 100644
index 00000000000..46343a7b86e
--- /dev/null
+++ b/src/ci/citool/Cargo.lock
@@ -0,0 +1,1098 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "adler2"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
+
+[[package]]
+name = "anstream"
+version = "0.6.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is_terminal_polyfill",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
+dependencies = [
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e"
+dependencies = [
+ "anstyle",
+ "once_cell",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.95"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
+
+[[package]]
+name = "base64"
+version = "0.22.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
+
+[[package]]
+name = "build_helper"
+version = "0.1.0"
+dependencies = [
+ "serde",
+ "serde_derive",
+]
+
+[[package]]
+name = "bytes"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9"
+
+[[package]]
+name = "cc"
+version = "1.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c"
+dependencies = [
+ "shlex",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "citool"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "build_helper",
+ "clap",
+ "csv",
+ "insta",
+ "serde",
+ "serde_json",
+ "serde_yaml",
+ "ureq",
+]
+
+[[package]]
+name = "clap"
+version = "4.5.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e77c3243bd94243c03672cb5154667347c457ca271254724f9f393aee1c05ff"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.5.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
+
+[[package]]
+name = "colorchoice"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
+
+[[package]]
+name = "console"
+version = "0.15.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea3c6ecd8059b57859df5c69830340ed3c41d30e3da0c1cbed90a96ac853041b"
+dependencies = [
+ "encode_unicode",
+ "libc",
+ "once_cell",
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "cookie"
+version = "0.18.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747"
+dependencies = [
+ "percent-encoding",
+ "time",
+ "version_check",
+]
+
+[[package]]
+name = "cookie_store"
+version = "0.21.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2eac901828f88a5241ee0600950ab981148a18f2f756900ffba1b125ca6a3ef9"
+dependencies = [
+ "cookie",
+ "document-features",
+ "idna",
+ "indexmap",
+ "log",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "time",
+ "url",
+]
+
+[[package]]
+name = "crc32fast"
+version = "1.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "csv"
+version = "1.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf"
+dependencies = [
+ "csv-core",
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "csv-core"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d02f3b0da4c6504f86e9cd789d8dbafab48c2321be74e9987593de5a894d93d"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "deranged"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
+dependencies = [
+ "powerfmt",
+]
+
+[[package]]
+name = "displaydoc"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "document-features"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d"
+dependencies = [
+ "litrs",
+]
+
+[[package]]
+name = "encode_unicode"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
+
+[[package]]
+name = "equivalent"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+
+[[package]]
+name = "flate2"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc"
+dependencies = [
+ "crc32fast",
+ "miniz_oxide",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "form_urlencoded"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.15.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
+
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "http"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea"
+dependencies = [
+ "bytes",
+ "fnv",
+ "itoa",
+]
+
+[[package]]
+name = "httparse"
+version = "1.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
+
+[[package]]
+name = "icu_collections"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
+dependencies = [
+ "displaydoc",
+ "yoke",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
+dependencies = [
+ "displaydoc",
+ "litemap",
+ "tinystr",
+ "writeable",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid_transform"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
+dependencies = [
+ "displaydoc",
+ "icu_locid",
+ "icu_locid_transform_data",
+ "icu_provider",
+ "tinystr",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid_transform_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
+
+[[package]]
+name = "icu_normalizer"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
+dependencies = [
+ "displaydoc",
+ "icu_collections",
+ "icu_normalizer_data",
+ "icu_properties",
+ "icu_provider",
+ "smallvec",
+ "utf16_iter",
+ "utf8_iter",
+ "write16",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_normalizer_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
+
+[[package]]
+name = "icu_properties"
+version = "1.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5"
+dependencies = [
+ "displaydoc",
+ "icu_collections",
+ "icu_locid_transform",
+ "icu_properties_data",
+ "icu_provider",
+ "tinystr",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_properties_data"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
+
+[[package]]
+name = "icu_provider"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
+dependencies = [
+ "displaydoc",
+ "icu_locid",
+ "icu_provider_macros",
+ "stable_deref_trait",
+ "tinystr",
+ "writeable",
+ "yoke",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_provider_macros"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "idna"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
+dependencies = [
+ "idna_adapter",
+ "smallvec",
+ "utf8_iter",
+]
+
+[[package]]
+name = "idna_adapter"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71"
+dependencies = [
+ "icu_normalizer",
+ "icu_properties",
+]
+
+[[package]]
+name = "indexmap"
+version = "2.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+]
+
+[[package]]
+name = "insta"
+version = "1.42.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71c1b125e30d93896b365e156c33dadfffab45ee8400afcbba4752f59de08a86"
+dependencies = [
+ "console",
+ "linked-hash-map",
+ "once_cell",
+ "pin-project",
+ "similar",
+]
+
+[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
+
+[[package]]
+name = "itoa"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
+
+[[package]]
+name = "libc"
+version = "0.2.169"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
+
+[[package]]
+name = "linked-hash-map"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
+
+[[package]]
+name = "litemap"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856"
+
+[[package]]
+name = "litrs"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5"
+
+[[package]]
+name = "log"
+version = "0.4.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e"
+
+[[package]]
+name = "memchr"
+version = "2.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5"
+dependencies = [
+ "adler2",
+]
+
+[[package]]
+name = "num-conv"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
+
+[[package]]
+name = "once_cell"
+version = "1.20.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e"
+
+[[package]]
+name = "percent-encoding"
+version = "2.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
+
+[[package]]
+name = "pin-project"
+version = "1.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dfe2e71e1471fe07709406bf725f710b02927c9c54b2b5b2ec0e8087d97c327d"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6e859e6e5bd50440ab63c47e3ebabc90f26251f7c73c3d3e837b74a1cc3fa67"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "powerfmt"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.93"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "ring"
+version = "0.17.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da5349ae27d3887ca812fb375b45a4fbb36d8d12d2df394968cd86e35683fe73"
+dependencies = [
+ "cc",
+ "cfg-if",
+ "getrandom",
+ "libc",
+ "untrusted",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "rustls"
+version = "0.23.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395"
+dependencies = [
+ "log",
+ "once_cell",
+ "ring",
+ "rustls-pki-types",
+ "rustls-webpki",
+ "subtle",
+ "zeroize",
+]
+
+[[package]]
+name = "rustls-pemfile"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
+dependencies = [
+ "rustls-pki-types",
+]
+
+[[package]]
+name = "rustls-pki-types"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c"
+
+[[package]]
+name = "rustls-webpki"
+version = "0.102.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9"
+dependencies = [
+ "ring",
+ "rustls-pki-types",
+ "untrusted",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd"
+
+[[package]]
+name = "serde"
+version = "1.0.217"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.217"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.138"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949"
+dependencies = [
+ "itoa",
+ "memchr",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "serde_yaml"
+version = "0.9.34+deprecated"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
+dependencies = [
+ "indexmap",
+ "itoa",
+ "ryu",
+ "serde",
+ "unsafe-libyaml",
+]
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "similar"
+version = "2.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa"
+
+[[package]]
+name = "smallvec"
+version = "1.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd"
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
+[[package]]
+name = "subtle"
+version = "2.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
+
+[[package]]
+name = "syn"
+version = "2.0.98"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "synstructure"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "time"
+version = "0.3.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb041120f25f8fbe8fd2dbe4671c7c2ed74d83be2e7a77529bf7e0790ae3f472"
+dependencies = [
+ "deranged",
+ "itoa",
+ "num-conv",
+ "powerfmt",
+ "serde",
+ "time-core",
+ "time-macros",
+]
+
+[[package]]
+name = "time-core"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "765c97a5b985b7c11d7bc27fa927dc4fe6af3a6dfb021d28deb60d3bf51e76ef"
+
+[[package]]
+name = "time-macros"
+version = "0.2.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8093bc3e81c3bc5f7879de09619d06c9a5a5e45ca44dfeeb7225bae38005c5c"
+dependencies = [
+ "num-conv",
+ "time-core",
+]
+
+[[package]]
+name = "tinystr"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
+dependencies = [
+ "displaydoc",
+ "zerovec",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034"
+
+[[package]]
+name = "unsafe-libyaml"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
+
+[[package]]
+name = "untrusted"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
+
+[[package]]
+name = "ureq"
+version = "3.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06f78313c985f2fba11100dd06d60dd402d0cabb458af4d94791b8e09c025323"
+dependencies = [
+ "base64",
+ "cookie_store",
+ "flate2",
+ "log",
+ "percent-encoding",
+ "rustls",
+ "rustls-pemfile",
+ "rustls-pki-types",
+ "serde",
+ "serde_json",
+ "ureq-proto",
+ "utf-8",
+ "webpki-roots",
+]
+
+[[package]]
+name = "ureq-proto"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64adb55464bad1ab1aa9229133d0d59d2f679180f4d15f0d9debe616f541f25e"
+dependencies = [
+ "base64",
+ "http",
+ "httparse",
+ "log",
+]
+
+[[package]]
+name = "url"
+version = "2.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "percent-encoding",
+]
+
+[[package]]
+name = "utf-8"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
+
+[[package]]
+name = "utf16_iter"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
+
+[[package]]
+name = "utf8_iter"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
+
+[[package]]
+name = "utf8parse"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
+
+[[package]]
+name = "version_check"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "webpki-roots"
+version = "0.26.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9"
+dependencies = [
+ "rustls-pki-types",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.59.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+
+[[package]]
+name = "write16"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
+
+[[package]]
+name = "writeable"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
+
+[[package]]
+name = "yoke"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
+dependencies = [
+ "serde",
+ "stable_deref_trait",
+ "yoke-derive",
+ "zerofrom",
+]
+
+[[package]]
+name = "yoke-derive"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
+[[package]]
+name = "zerofrom"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
+dependencies = [
+ "zerofrom-derive",
+]
+
+[[package]]
+name = "zerofrom-derive"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
+[[package]]
+name = "zeroize"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
+
+[[package]]
+name = "zerovec"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079"
+dependencies = [
+ "yoke",
+ "zerofrom",
+ "zerovec-derive",
+]
+
+[[package]]
+name = "zerovec-derive"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
diff --git a/src/ci/citool/Cargo.toml b/src/ci/citool/Cargo.toml
new file mode 100644
index 00000000000..c486f2977a1
--- /dev/null
+++ b/src/ci/citool/Cargo.toml
@@ -0,0 +1,27 @@
+[package]
+name = "citool"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+anyhow = "1"
+clap = { version = "4.5", features = ["derive"] }
+csv = "1"
+serde = { version = "1", features = ["derive"] }
+serde_yaml = "0.9"
+serde_json = "1"
+ureq = { version = "3", features = ["json"] }
+
+build_helper = { path = "../../build_helper" }
+
+[dev-dependencies]
+insta = "1"
+
+# Tell cargo that citool is its own workspace.
+# If this is omitted, cargo will look for a workspace elsewhere.
+# We want to avoid this, since citool is independent of the other crates.
+[workspace]
+
+# Make compilation faster
+[profile.dev]
+debug = 0
diff --git a/src/ci/citool/README.md b/src/ci/citool/README.md
new file mode 100644
index 00000000000..685a255f152
--- /dev/null
+++ b/src/ci/citool/README.md
@@ -0,0 +1,2 @@
+# CI tooling
+This is a simple Rust script that determines which jobs should be executed on CI based on the situation (pull request, try job, merge attempt). It also provides a simple way of executing (some) CI jobs locally.
diff --git a/src/ci/citool/src/cpu_usage.rs b/src/ci/citool/src/cpu_usage.rs
new file mode 100644
index 00000000000..fa9a1203f41
--- /dev/null
+++ b/src/ci/citool/src/cpu_usage.rs
@@ -0,0 +1,24 @@
+use std::path::Path;
+
+/// Loads CPU usage records from a CSV generated by the `src/ci/scripts/collect-cpu-stats.sh`
+/// script.
+pub fn load_cpu_usage(path: &Path) -> anyhow::Result<Vec<f64>> {
+    let reader = csv::ReaderBuilder::new().flexible(true).from_path(path)?;
+
+    let mut entries = vec![];
+    for row in reader.into_records() {
+        let row = row?;
+        let cols = row.into_iter().collect::<Vec<&str>>();
+
+        // The log might contain incomplete rows or some Python exception
+        if cols.len() == 2 {
+            if let Ok(idle) = cols[1].parse::<f64>() {
+                entries.push(100.0 - idle);
+            } else {
+                eprintln!("Warning: cannot parse CPU CSV entry {}", cols[1]);
+            }
+        }
+    }
+
+    Ok(entries)
+}
diff --git a/src/ci/citool/src/datadog.rs b/src/ci/citool/src/datadog.rs
new file mode 100644
index 00000000000..837257420d6
--- /dev/null
+++ b/src/ci/citool/src/datadog.rs
@@ -0,0 +1,43 @@
+use anyhow::Context;
+
+use crate::utils::load_env_var;
+
+/// Uploads a custom CI pipeline metric to Datadog.
+/// Expects to be executed from within the context of a GitHub Actions job.
+pub fn upload_datadog_metric(name: &str, value: f64) -> anyhow::Result<()> {
+    let datadog_api_key = load_env_var("DATADOG_API_KEY")?;
+    let github_server_url = load_env_var("GITHUB_SERVER_URL")?;
+    let github_repository = load_env_var("GITHUB_REPOSITORY")?;
+    let github_run_id = load_env_var("GITHUB_RUN_ID")?;
+    let github_run_attempt = load_env_var("GITHUB_RUN_ATTEMPT")?;
+    let github_job = load_env_var("GITHUB_JOB")?;
+    let dd_github_job_name = load_env_var("DD_GITHUB_JOB_NAME")?;
+
+    // This API endpoint is not documented in Datadog's API reference currently.
+    // It was reverse-engineered from the `datadog-ci measure` npm command.
+    ureq::post("https://api.datadoghq.com/api/v2/ci/pipeline/metrics")
+        .header("DD-API-KEY", datadog_api_key)
+        .send_json(serde_json::json!({
+            "data": {
+                "attributes": {
+                    "ci_env": {
+                        "GITHUB_SERVER_URL": github_server_url,
+                        "GITHUB_REPOSITORY": github_repository,
+                        "GITHUB_RUN_ID": github_run_id,
+                        "GITHUB_RUN_ATTEMPT": github_run_attempt,
+                        "GITHUB_JOB": github_job,
+                        "DD_GITHUB_JOB_NAME": dd_github_job_name
+                    },
+                    // Job level
+                    "ci_level": 1,
+                    "metrics": {
+                        name: value
+                    },
+                    "provider": "github"
+                },
+                "type": "ci_custom_metric"
+            }
+        }))
+        .context("cannot send metric to DataDog")?;
+    Ok(())
+}
diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs
new file mode 100644
index 00000000000..a1e5658be36
--- /dev/null
+++ b/src/ci/citool/src/main.rs
@@ -0,0 +1,412 @@
+mod cpu_usage;
+mod datadog;
+mod metrics;
+mod utils;
+
+use std::collections::BTreeMap;
+use std::path::{Path, PathBuf};
+use std::process::Command;
+
+use anyhow::Context;
+use clap::Parser;
+use serde_yaml::Value;
+
+use crate::cpu_usage::load_cpu_usage;
+use crate::datadog::upload_datadog_metric;
+use crate::metrics::postprocess_metrics;
+use crate::utils::load_env_var;
+
+const CI_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/..");
+const DOCKER_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../docker");
+const JOBS_YML_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../github-actions/jobs.yml");
+
+/// Representation of a job loaded from the `src/ci/github-actions/jobs.yml` file.
+#[derive(serde::Deserialize, Debug, Clone)]
+struct Job {
+    /// Name of the job, e.g. mingw-check
+    name: String,
+    /// GitHub runner on which the job should be executed
+    os: String,
+    env: BTreeMap<String, Value>,
+    /// Should the job be only executed on a specific channel?
+    #[serde(default)]
+    only_on_channel: Option<String>,
+    /// Rest of attributes that will be passed through to GitHub actions
+    #[serde(flatten)]
+    extra_keys: BTreeMap<String, Value>,
+}
+
+impl Job {
+    fn is_linux(&self) -> bool {
+        self.os.contains("ubuntu")
+    }
+
+    /// By default, the Docker image of a job is based on its name.
+    /// However, it can be overridden by its IMAGE environment variable.
+    fn image(&self) -> String {
+        self.env
+            .get("IMAGE")
+            .map(|v| v.as_str().expect("IMAGE value should be a string").to_string())
+            .unwrap_or_else(|| self.name.clone())
+    }
+}
+
+#[derive(serde::Deserialize, Debug)]
+struct JobEnvironments {
+    #[serde(rename = "pr")]
+    pr_env: BTreeMap<String, Value>,
+    #[serde(rename = "try")]
+    try_env: BTreeMap<String, Value>,
+    #[serde(rename = "auto")]
+    auto_env: BTreeMap<String, Value>,
+}
+
+#[derive(serde::Deserialize, Debug)]
+struct JobDatabase {
+    #[serde(rename = "pr")]
+    pr_jobs: Vec<Job>,
+    #[serde(rename = "try")]
+    try_jobs: Vec<Job>,
+    #[serde(rename = "auto")]
+    auto_jobs: Vec<Job>,
+
+    /// Shared environments for the individual run types.
+    envs: JobEnvironments,
+}
+
+impl JobDatabase {
+    fn find_auto_job_by_name(&self, name: &str) -> Option<Job> {
+        self.auto_jobs.iter().find(|j| j.name == name).cloned()
+    }
+}
+
+fn load_job_db(path: &Path) -> anyhow::Result<JobDatabase> {
+    let db = utils::read_to_string(path)?;
+    let mut db: Value = serde_yaml::from_str(&db)?;
+
+    // We need to expand merge keys (<<), because serde_yaml can't deal with them
+    // `apply_merge` only applies the merge once, so do it a few times to unwrap nested merges.
+    db.apply_merge()?;
+    db.apply_merge()?;
+
+    let db: JobDatabase = serde_yaml::from_value(db)?;
+    Ok(db)
+}
+
+/// Representation of a job outputted to a GitHub Actions workflow.
+#[derive(serde::Serialize, Debug)]
+struct GithubActionsJob {
+    /// The main identifier of the job, used by CI scripts to determine what should be executed.
+    name: String,
+    /// Helper label displayed in GitHub Actions interface, containing the job name and a run type
+    /// prefix (PR/try/auto).
+    full_name: String,
+    os: String,
+    env: BTreeMap<String, serde_json::Value>,
+    #[serde(flatten)]
+    extra_keys: BTreeMap<String, serde_json::Value>,
+}
+
+/// Type of workflow that is being executed on CI
+#[derive(Debug)]
+enum RunType {
+    /// Workflows that run after a push to a PR branch
+    PullRequest,
+    /// Try run started with @bors try
+    TryJob { custom_jobs: Option<Vec<String>> },
+    /// Merge attempt workflow
+    AutoJob,
+}
+
+struct GitHubContext {
+    event_name: String,
+    branch_ref: String,
+    commit_message: Option<String>,
+}
+
+impl GitHubContext {
+    fn get_run_type(&self) -> Option<RunType> {
+        match (self.event_name.as_str(), self.branch_ref.as_str()) {
+            ("pull_request", _) => Some(RunType::PullRequest),
+            ("push", "refs/heads/try-perf") => Some(RunType::TryJob { custom_jobs: None }),
+            ("push", "refs/heads/try" | "refs/heads/automation/bors/try") => {
+                let custom_jobs = self.get_custom_jobs();
+                let custom_jobs = if !custom_jobs.is_empty() { Some(custom_jobs) } else { None };
+                Some(RunType::TryJob { custom_jobs })
+            }
+            ("push", "refs/heads/auto") => Some(RunType::AutoJob),
+            _ => None,
+        }
+    }
+
+    /// Tries to parse names of specific CI jobs that should be executed in the form of
+    /// try-job: <job-name>
+    /// from the commit message of the passed GitHub context.
+    fn get_custom_jobs(&self) -> Vec<String> {
+        if let Some(ref msg) = self.commit_message {
+            msg.lines()
+                .filter_map(|line| line.trim().strip_prefix("try-job: "))
+                .map(|l| l.trim().to_string())
+                .collect()
+        } else {
+            vec![]
+        }
+    }
+}
+
+fn load_github_ctx() -> anyhow::Result<GitHubContext> {
+    let event_name = load_env_var("GITHUB_EVENT_NAME")?;
+    let commit_message =
+        if event_name == "push" { Some(load_env_var("COMMIT_MESSAGE")?) } else { None };
+
+    Ok(GitHubContext { event_name, branch_ref: load_env_var("GITHUB_REF")?, commit_message })
+}
+
+/// Skip CI jobs that are not supposed to be executed on the given `channel`.
+fn skip_jobs(jobs: Vec<Job>, channel: &str) -> Vec<Job> {
+    jobs.into_iter()
+        .filter(|job| {
+            job.only_on_channel.is_none() || job.only_on_channel.as_deref() == Some(channel)
+        })
+        .collect()
+}
+
+fn yaml_map_to_json(map: &BTreeMap<String, Value>) -> BTreeMap<String, serde_json::Value> {
+    map.into_iter()
+        .map(|(key, value)| {
+            (
+                key.clone(),
+                serde_json::to_value(&value).expect("Cannot convert map value from YAML to JSON"),
+            )
+        })
+        .collect()
+}
+
+fn calculate_jobs(
+    run_type: &RunType,
+    db: &JobDatabase,
+    channel: &str,
+) -> anyhow::Result<Vec<GithubActionsJob>> {
+    let (jobs, prefix, base_env) = match run_type {
+        RunType::PullRequest => (db.pr_jobs.clone(), "PR", &db.envs.pr_env),
+        RunType::TryJob { custom_jobs } => {
+            let jobs = if let Some(custom_jobs) = custom_jobs {
+                if custom_jobs.len() > 10 {
+                    return Err(anyhow::anyhow!(
+                        "It is only possible to schedule up to 10 custom jobs, received {} custom jobs",
+                        custom_jobs.len()
+                    ));
+                }
+
+                let mut jobs = vec![];
+                let mut unknown_jobs = vec![];
+                for custom_job in custom_jobs {
+                    if let Some(job) = db.find_auto_job_by_name(custom_job) {
+                        jobs.push(job);
+                    } else {
+                        unknown_jobs.push(custom_job.clone());
+                    }
+                }
+                if !unknown_jobs.is_empty() {
+                    return Err(anyhow::anyhow!(
+                        "Custom job(s) `{}` not found in auto jobs",
+                        unknown_jobs.join(", ")
+                    ));
+                }
+                jobs
+            } else {
+                db.try_jobs.clone()
+            };
+            (jobs, "try", &db.envs.try_env)
+        }
+        RunType::AutoJob => (db.auto_jobs.clone(), "auto", &db.envs.auto_env),
+    };
+    let jobs = skip_jobs(jobs, channel);
+    let jobs = jobs
+        .into_iter()
+        .map(|job| {
+            let mut env: BTreeMap<String, serde_json::Value> = yaml_map_to_json(base_env);
+            env.extend(yaml_map_to_json(&job.env));
+            let full_name = format!("{prefix} - {}", job.name);
+
+            GithubActionsJob {
+                name: job.name,
+                full_name,
+                os: job.os,
+                env,
+                extra_keys: yaml_map_to_json(&job.extra_keys),
+            }
+        })
+        .collect();
+
+    Ok(jobs)
+}
+
+fn calculate_job_matrix(
+    db: JobDatabase,
+    gh_ctx: GitHubContext,
+    channel: &str,
+) -> anyhow::Result<()> {
+    let run_type = gh_ctx.get_run_type().ok_or_else(|| {
+        anyhow::anyhow!("Cannot determine the type of workflow that is being executed")
+    })?;
+    eprintln!("Run type: {run_type:?}");
+
+    let jobs = calculate_jobs(&run_type, &db, channel)?;
+    if jobs.is_empty() {
+        return Err(anyhow::anyhow!("Computed job list is empty"));
+    }
+
+    let run_type = match run_type {
+        RunType::PullRequest => "pr",
+        RunType::TryJob { .. } => "try",
+        RunType::AutoJob => "auto",
+    };
+
+    eprintln!("Output");
+    eprintln!("jobs={jobs:?}");
+    eprintln!("run_type={run_type}");
+    println!("jobs={}", serde_json::to_string(&jobs)?);
+    println!("run_type={run_type}");
+
+    Ok(())
+}
+
+fn find_linux_job<'a>(jobs: &'a [Job], name: &str) -> anyhow::Result<&'a Job> {
+    let Some(job) = jobs.iter().find(|j| j.name == name) else {
+        let available_jobs: Vec<&Job> = jobs.iter().filter(|j| j.is_linux()).collect();
+        let mut available_jobs =
+            available_jobs.iter().map(|j| j.name.to_string()).collect::<Vec<_>>();
+        available_jobs.sort();
+        return Err(anyhow::anyhow!(
+            "Job {name} not found. The following jobs are available:\n{}",
+            available_jobs.join(", ")
+        ));
+    };
+    if !job.is_linux() {
+        return Err(anyhow::anyhow!("Only Linux jobs can be executed locally"));
+    }
+
+    Ok(job)
+}
+
+fn run_workflow_locally(db: JobDatabase, job_type: JobType, name: String) -> anyhow::Result<()> {
+    let jobs = match job_type {
+        JobType::Auto => &db.auto_jobs,
+        JobType::PR => &db.pr_jobs,
+    };
+    let job = find_linux_job(jobs, &name).with_context(|| format!("Cannot find job {name}"))?;
+
+    let mut custom_env: BTreeMap<String, String> = BTreeMap::new();
+    // Replicate src/ci/scripts/setup-environment.sh
+    // Adds custom environment variables to the job
+    if name.starts_with("dist-") {
+        if name.ends_with("-alt") {
+            custom_env.insert("DEPLOY_ALT".to_string(), "1".to_string());
+        } else {
+            custom_env.insert("DEPLOY".to_string(), "1".to_string());
+        }
+    }
+    custom_env.extend(job.env.iter().map(|(key, value)| {
+        let value = match value {
+            Value::Bool(value) => value.to_string(),
+            Value::Number(value) => value.to_string(),
+            Value::String(value) => value.clone(),
+            _ => panic!("Unexpected type for environment variable {key} Only bool/number/string is supported.")
+        };
+        (key.clone(), value)
+    }));
+
+    let mut cmd = Command::new(Path::new(DOCKER_DIRECTORY).join("run.sh"));
+    cmd.arg(job.image());
+    cmd.envs(custom_env);
+
+    eprintln!("Executing {cmd:?}");
+
+    let result = cmd.spawn()?.wait()?;
+    if !result.success() { Err(anyhow::anyhow!("Job failed")) } else { Ok(()) }
+}
+
+fn upload_ci_metrics(cpu_usage_csv: &Path) -> anyhow::Result<()> {
+    let usage = load_cpu_usage(cpu_usage_csv).context("Cannot load CPU usage from input CSV")?;
+    eprintln!("CPU usage\n{usage:?}");
+
+    let avg = if !usage.is_empty() { usage.iter().sum::<f64>() / usage.len() as f64 } else { 0.0 };
+    eprintln!("CPU usage average: {avg}");
+
+    upload_datadog_metric("avg-cpu-usage", avg).context("Cannot upload Datadog metric")?;
+
+    Ok(())
+}
+
+#[derive(clap::Parser)]
+enum Args {
+    /// Calculate a list of jobs that should be executed on CI.
+    /// Should only be used on CI inside GitHub actions.
+    CalculateJobMatrix {
+        #[clap(long)]
+        jobs_file: Option<PathBuf>,
+    },
+    /// Execute a given CI job locally.
+    #[clap(name = "run-local")]
+    RunJobLocally {
+        /// Name of the job that should be executed.
+        name: String,
+        /// Type of the job that should be executed.
+        #[clap(long = "type", default_value = "auto")]
+        job_type: JobType,
+    },
+    /// Postprocess the metrics.json file generated by bootstrap.
+    PostprocessMetrics {
+        /// Path to the metrics.json file
+        metrics_path: PathBuf,
+        /// Path to a file where the postprocessed metrics summary will be stored.
+        /// Usually, this will be GITHUB_STEP_SUMMARY on CI.
+        summary_path: PathBuf,
+    },
+    /// Upload CI metrics to Datadog.
+    UploadBuildMetrics {
+        /// Path to a CSV containing the CI job CPU usage.
+        cpu_usage_csv: PathBuf,
+    },
+}
+
+#[derive(clap::ValueEnum, Clone)]
+enum JobType {
+    /// Merge attempt ("auto") job
+    Auto,
+    /// Pull request job
+    PR,
+}
+
+fn main() -> anyhow::Result<()> {
+    let args = Args::parse();
+    let default_jobs_file = Path::new(JOBS_YML_PATH);
+    let load_db = |jobs_path| load_job_db(jobs_path).context("Cannot load jobs.yml");
+
+    match args {
+        Args::CalculateJobMatrix { jobs_file } => {
+            let jobs_path = jobs_file.as_deref().unwrap_or(default_jobs_file);
+            let gh_ctx = load_github_ctx()
+                .context("Cannot load environment variables from GitHub Actions")?;
+            let channel = utils::read_to_string(Path::new(CI_DIRECTORY).join("channel"))
+                .context("Cannot read channel file")?
+                .trim()
+                .to_string();
+
+            calculate_job_matrix(load_db(jobs_path)?, gh_ctx, &channel)
+                .context("Failed to calculate job matrix")?;
+        }
+        Args::RunJobLocally { job_type, name } => {
+            run_workflow_locally(load_db(default_jobs_file)?, job_type, name)?;
+        }
+        Args::UploadBuildMetrics { cpu_usage_csv } => {
+            upload_ci_metrics(&cpu_usage_csv)?;
+        }
+        Args::PostprocessMetrics { metrics_path, summary_path } => {
+            postprocess_metrics(&metrics_path, &summary_path)?;
+        }
+    }
+
+    Ok(())
+}
diff --git a/src/ci/citool/src/metrics.rs b/src/ci/citool/src/metrics.rs
new file mode 100644
index 00000000000..2386413ed6b
--- /dev/null
+++ b/src/ci/citool/src/metrics.rs
@@ -0,0 +1,164 @@
+use std::collections::BTreeMap;
+use std::fs::File;
+use std::io::Write;
+use std::path::Path;
+
+use anyhow::Context;
+use build_helper::metrics::{
+    BuildStep, JsonNode, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, format_build_steps,
+};
+
+pub fn postprocess_metrics(metrics_path: &Path, summary_path: &Path) -> anyhow::Result<()> {
+    let metrics = load_metrics(metrics_path)?;
+
+    let mut file = File::options()
+        .append(true)
+        .create(true)
+        .open(summary_path)
+        .with_context(|| format!("Cannot open summary file at {summary_path:?}"))?;
+
+    if !metrics.invocations.is_empty() {
+        writeln!(file, "# Bootstrap steps")?;
+        record_bootstrap_step_durations(&metrics, &mut file)?;
+        record_test_suites(&metrics, &mut file)?;
+    }
+
+    Ok(())
+}
+
+fn record_bootstrap_step_durations(metrics: &JsonRoot, file: &mut File) -> anyhow::Result<()> {
+    for invocation in &metrics.invocations {
+        let step = BuildStep::from_invocation(invocation);
+        let table = format_build_steps(&step);
+        eprintln!("Step `{}`\n{table}\n", invocation.cmdline);
+        writeln!(
+            file,
+            r"<details>
+<summary>{}</summary>
+<pre><code>{table}</code></pre>
+</details>
+",
+            invocation.cmdline
+        )?;
+    }
+    eprintln!("Recorded {} bootstrap invocation(s)", metrics.invocations.len());
+
+    Ok(())
+}
+
+fn record_test_suites(metrics: &JsonRoot, file: &mut File) -> anyhow::Result<()> {
+    let suites = get_test_suites(&metrics);
+
+    if !suites.is_empty() {
+        let aggregated = aggregate_test_suites(&suites);
+        let table = render_table(aggregated);
+        writeln!(file, "\n# Test results\n")?;
+        writeln!(file, "{table}")?;
+    } else {
+        eprintln!("No test suites found in metrics");
+    }
+
+    Ok(())
+}
+
+fn render_table(suites: BTreeMap<String, TestSuiteRecord>) -> String {
+    use std::fmt::Write;
+
+    let mut table = "| Test suite | Passed ✅ | Ignored 🚫 | Failed  ❌ |\n".to_string();
+    writeln!(table, "|:------|------:|------:|------:|").unwrap();
+
+    fn write_row(
+        buffer: &mut String,
+        name: &str,
+        record: &TestSuiteRecord,
+        surround: &str,
+    ) -> std::fmt::Result {
+        let TestSuiteRecord { passed, ignored, failed } = record;
+        let total = (record.passed + record.ignored + record.failed) as f64;
+        let passed_pct = ((*passed as f64) / total) * 100.0;
+        let ignored_pct = ((*ignored as f64) / total) * 100.0;
+        let failed_pct = ((*failed as f64) / total) * 100.0;
+
+        write!(buffer, "| {surround}{name}{surround} |")?;
+        write!(buffer, " {surround}{passed} ({passed_pct:.0}%){surround} |")?;
+        write!(buffer, " {surround}{ignored} ({ignored_pct:.0}%){surround} |")?;
+        writeln!(buffer, " {surround}{failed} ({failed_pct:.0}%){surround} |")?;
+
+        Ok(())
+    }
+
+    let mut total = TestSuiteRecord::default();
+    for (name, record) in suites {
+        write_row(&mut table, &name, &record, "").unwrap();
+        total.passed += record.passed;
+        total.ignored += record.ignored;
+        total.failed += record.failed;
+    }
+    write_row(&mut table, "Total", &total, "**").unwrap();
+    table
+}
+
+#[derive(Default)]
+struct TestSuiteRecord {
+    passed: u64,
+    ignored: u64,
+    failed: u64,
+}
+
+fn aggregate_test_suites(suites: &[&TestSuite]) -> BTreeMap<String, TestSuiteRecord> {
+    let mut records: BTreeMap<String, TestSuiteRecord> = BTreeMap::new();
+    for suite in suites {
+        let name = match &suite.metadata {
+            TestSuiteMetadata::CargoPackage { crates, stage, .. } => {
+                format!("{} (stage {stage})", crates.join(", "))
+            }
+            TestSuiteMetadata::Compiletest { suite, stage, .. } => {
+                format!("{suite} (stage {stage})")
+            }
+        };
+        let record = records.entry(name).or_default();
+        for test in &suite.tests {
+            match test.outcome {
+                TestOutcome::Passed => {
+                    record.passed += 1;
+                }
+                TestOutcome::Failed => {
+                    record.failed += 1;
+                }
+                TestOutcome::Ignored { .. } => {
+                    record.ignored += 1;
+                }
+            }
+        }
+    }
+    records
+}
+
+fn get_test_suites(metrics: &JsonRoot) -> Vec<&TestSuite> {
+    fn visit_test_suites<'a>(nodes: &'a [JsonNode], suites: &mut Vec<&'a TestSuite>) {
+        for node in nodes {
+            match node {
+                JsonNode::RustbuildStep { children, .. } => {
+                    visit_test_suites(&children, suites);
+                }
+                JsonNode::TestSuite(suite) => {
+                    suites.push(&suite);
+                }
+            }
+        }
+    }
+
+    let mut suites = vec![];
+    for invocation in &metrics.invocations {
+        visit_test_suites(&invocation.children, &mut suites);
+    }
+    suites
+}
+
+fn load_metrics(path: &Path) -> anyhow::Result<JsonRoot> {
+    let metrics = std::fs::read_to_string(path)
+        .with_context(|| format!("Cannot read JSON metrics from {path:?}"))?;
+    let metrics: JsonRoot = serde_json::from_str(&metrics)
+        .with_context(|| format!("Cannot deserialize JSON metrics from {path:?}"))?;
+    Ok(metrics)
+}
diff --git a/src/ci/citool/src/utils.rs b/src/ci/citool/src/utils.rs
new file mode 100644
index 00000000000..9cc220987bd
--- /dev/null
+++ b/src/ci/citool/src/utils.rs
@@ -0,0 +1,11 @@
+use std::path::Path;
+
+use anyhow::Context;
+
+pub fn load_env_var(name: &str) -> anyhow::Result<String> {
+    std::env::var(name).with_context(|| format!("Cannot find environment variable `{name}`"))
+}
+
+pub fn read_to_string<P: AsRef<Path>>(path: P) -> anyhow::Result<String> {
+    std::fs::read_to_string(&path).with_context(|| format!("Cannot read file {:?}", path.as_ref()))
+}
diff --git a/src/ci/citool/tests/jobs.rs b/src/ci/citool/tests/jobs.rs
new file mode 100644
index 00000000000..1d81d58f893
--- /dev/null
+++ b/src/ci/citool/tests/jobs.rs
@@ -0,0 +1,64 @@
+use std::process::{Command, Stdio};
+
+const TEST_JOBS_YML_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/tests/test-jobs.yml");
+
+#[test]
+fn auto_jobs() {
+    let stdout = get_matrix("push", "commit", "refs/heads/auto");
+    insta::assert_snapshot!(stdout, @r#"
+    jobs=[{"name":"aarch64-gnu","full_name":"auto - aarch64-gnu","os":"ubuntu-22.04-arm","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"x86_64-gnu-llvm-18-1","full_name":"auto - x86_64-gnu-llvm-18-1","os":"ubuntu-24.04","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","DOCKER_SCRIPT":"stage_2_test_set1.sh","IMAGE":"x86_64-gnu-llvm-18","READ_ONLY_SRC":"0","RUST_BACKTRACE":1,"TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"aarch64-apple","full_name":"auto - aarch64-apple","os":"macos-14","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","MACOSX_DEPLOYMENT_TARGET":11.0,"MACOSX_STD_DEPLOYMENT_TARGET":11.0,"NO_DEBUG_ASSERTIONS":1,"NO_LLVM_ASSERTIONS":1,"NO_OVERFLOW_CHECKS":1,"RUSTC_RETRY_LINKER_ON_SEGFAULT":1,"RUST_CONFIGURE_ARGS":"--enable-sanitizers --enable-profiler --set rust.jemalloc","SCRIPT":"./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin","SELECT_XCODE":"/Applications/Xcode_15.4.app","TOOLSTATE_PUBLISH":1,"USE_XCODE_CLANG":1}},{"name":"dist-i686-msvc","full_name":"auto - dist-i686-msvc","os":"windows-2022","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_REQUIRE_ALL_TOOLS":1,"RUST_CONFIGURE_ARGS":"--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler","SCRIPT":"python x.py dist bootstrap --include-default-paths","TOOLSTATE_PUBLISH":1}}]
+    run_type=auto
+    "#);
+}
+
+#[test]
+fn try_jobs() {
+    let stdout = get_matrix("push", "commit", "refs/heads/try");
+    insta::assert_snapshot!(stdout, @r#"
+    jobs=[{"name":"dist-x86_64-linux","full_name":"try - dist-x86_64-linux","os":"ubuntu-22.04-16core-64gb","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_TRY_BUILD":1,"TOOLSTATE_PUBLISH":1}}]
+    run_type=try
+    "#);
+}
+
+#[test]
+fn try_custom_jobs() {
+    let stdout = get_matrix(
+        "push",
+        r#"This is a test PR
+
+try-job: aarch64-gnu
+try-job: dist-i686-msvc"#,
+        "refs/heads/try",
+    );
+    insta::assert_snapshot!(stdout, @r#"
+    jobs=[{"name":"aarch64-gnu","full_name":"try - aarch64-gnu","os":"ubuntu-22.04-arm","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","DIST_TRY_BUILD":1,"TOOLSTATE_PUBLISH":1},"free_disk":true},{"name":"dist-i686-msvc","full_name":"try - dist-i686-msvc","os":"windows-2022","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_REQUIRE_ALL_TOOLS":1,"DIST_TRY_BUILD":1,"RUST_CONFIGURE_ARGS":"--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler","SCRIPT":"python x.py dist bootstrap --include-default-paths","TOOLSTATE_PUBLISH":1}}]
+    run_type=try
+    "#);
+}
+
+#[test]
+fn pr_jobs() {
+    let stdout = get_matrix("pull_request", "commit", "refs/heads/pr/1234");
+    insta::assert_snapshot!(stdout, @r#"
+    jobs=[{"name":"mingw-check","full_name":"PR - mingw-check","os":"ubuntu-24.04","env":{"PR_CI_JOB":1},"free_disk":true},{"name":"mingw-check-tidy","full_name":"PR - mingw-check-tidy","os":"ubuntu-24.04","env":{"PR_CI_JOB":1},"continue_on_error":true,"free_disk":true}]
+    run_type=pr
+    "#);
+}
+
+fn get_matrix(event_name: &str, commit_msg: &str, branch_ref: &str) -> String {
+    let output = Command::new("cargo")
+        .args(["run", "-q", "calculate-job-matrix", "--jobs-file", TEST_JOBS_YML_PATH])
+        .env("GITHUB_EVENT_NAME", event_name)
+        .env("COMMIT_MESSAGE", commit_msg)
+        .env("GITHUB_REF", branch_ref)
+        .stdout(Stdio::piped())
+        .output()
+        .expect("Failed to execute command");
+
+    let stdout = String::from_utf8(output.stdout).unwrap();
+    let stderr = String::from_utf8(output.stderr).unwrap();
+    if !output.status.success() {
+        panic!("cargo run failed: {}\n{}", stdout, stderr);
+    }
+    stdout
+}
diff --git a/src/ci/citool/tests/test-jobs.yml b/src/ci/citool/tests/test-jobs.yml
new file mode 100644
index 00000000000..56b9ced2071
--- /dev/null
+++ b/src/ci/citool/tests/test-jobs.yml
@@ -0,0 +1,145 @@
+runners:
+  - &base-job
+    env: { }
+
+  - &job-linux-4c
+    os: ubuntu-24.04
+    # Free some disk space to avoid running out of space during the build.
+    free_disk: true
+    <<: *base-job
+
+  - &job-linux-16c
+    os: ubuntu-22.04-16core-64gb
+    <<: *base-job
+
+  - &job-macos-m1
+    os: macos-14
+    <<: *base-job
+
+  - &job-windows
+    os: windows-2022
+    <<: *base-job
+
+  - &job-aarch64-linux
+    # Free some disk space to avoid running out of space during the build.
+    free_disk: true
+    os: ubuntu-22.04-arm
+    <<: *base-job
+envs:
+  env-x86_64-apple-tests: &env-x86_64-apple-tests
+    SCRIPT: ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc -- --exact
+    RUST_CONFIGURE_ARGS: --build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc
+    RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
+    # Ensure that host tooling is tested on our minimum supported macOS version.
+    MACOSX_DEPLOYMENT_TARGET: 10.12
+    MACOSX_STD_DEPLOYMENT_TARGET: 10.12
+    SELECT_XCODE: /Applications/Xcode_15.2.app
+    NO_LLVM_ASSERTIONS: 1
+    NO_DEBUG_ASSERTIONS: 1
+    NO_OVERFLOW_CHECKS: 1
+
+  production:
+    &production
+    DEPLOY_BUCKET: rust-lang-ci2
+    # AWS_SECRET_ACCESS_KEYs are stored in GitHub's secrets storage, named
+    # AWS_SECRET_ACCESS_KEY_<keyid>. Including the key id in the name allows to
+    # rotate them in a single branch while keeping the old key in another
+    # branch, which wouldn't be possible if the key was named with the kind
+    # (caches, artifacts...).
+    CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZI5DHEBFL
+    ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55
+    AWS_REGION: us-west-1
+    TOOLSTATE_PUBLISH: 1
+
+  try:
+    <<: *production
+    # The following env var activates faster `try` builds in `opt-dist` by, e.g.
+    # - building only the more commonly useful components (we rarely need e.g. rust-docs in try
+    #   builds)
+    # - not running `opt-dist`'s post-optimization smoke tests on the resulting toolchain
+    #
+    # If you *want* these to happen however, temporarily comment it before triggering a try build.
+    DIST_TRY_BUILD: 1
+
+  auto:
+    <<: *production
+
+  pr:
+    PR_CI_JOB: 1
+
+# Jobs that run on each push to a pull request (PR)
+# These jobs automatically inherit envs.pr, to avoid repeating
+# it in each job definition.
+pr:
+  - name: mingw-check
+    <<: *job-linux-4c
+  - name: mingw-check-tidy
+    continue_on_error: true
+    <<: *job-linux-4c
+
+# Jobs that run when you perform a try build (@bors try)
+# These jobs automatically inherit envs.try, to avoid repeating
+# it in each job definition.
+try:
+  - name: dist-x86_64-linux
+    env:
+      CODEGEN_BACKENDS: llvm,cranelift
+    <<: *job-linux-16c
+
+# Main CI jobs that have to be green to merge a commit into master
+# These jobs automatically inherit envs.auto, to avoid repeating
+# it in each job definition.
+auto:
+  - name: aarch64-gnu
+    <<: *job-aarch64-linux
+
+  # The x86_64-gnu-llvm-18 job is split into multiple jobs to run tests in parallel.
+  # x86_64-gnu-llvm-18-1 skips tests that run in x86_64-gnu-llvm-18-{2,3}.
+  - name: x86_64-gnu-llvm-18-1
+    env:
+      RUST_BACKTRACE: 1
+      READ_ONLY_SRC: "0"
+      IMAGE: x86_64-gnu-llvm-18
+      DOCKER_SCRIPT: stage_2_test_set1.sh
+    <<: *job-linux-4c
+
+
+  ####################
+  #  macOS Builders  #
+  ####################
+
+  - name: aarch64-apple
+    env:
+      SCRIPT: ./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin
+      RUST_CONFIGURE_ARGS: >-
+        --enable-sanitizers
+        --enable-profiler
+        --set rust.jemalloc
+      RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
+      SELECT_XCODE: /Applications/Xcode_15.4.app
+      USE_XCODE_CLANG: 1
+      # Aarch64 tooling only needs to support macOS 11.0 and up as nothing else
+      # supports the hardware, so only need to test it there.
+      MACOSX_DEPLOYMENT_TARGET: 11.0
+      MACOSX_STD_DEPLOYMENT_TARGET: 11.0
+      NO_LLVM_ASSERTIONS: 1
+      NO_DEBUG_ASSERTIONS: 1
+      NO_OVERFLOW_CHECKS: 1
+    <<: *job-macos-m1
+
+  ######################
+  #  Windows Builders  #
+  ######################
+
+  - name: dist-i686-msvc
+    env:
+      RUST_CONFIGURE_ARGS: >-
+        --build=i686-pc-windows-msvc
+        --host=i686-pc-windows-msvc
+        --target=i686-pc-windows-msvc,i586-pc-windows-msvc
+        --enable-full-tools
+        --enable-profiler
+      SCRIPT: python x.py dist bootstrap --include-default-paths
+      DIST_REQUIRE_ALL_TOOLS: 1
+      CODEGEN_BACKENDS: llvm,cranelift
+    <<: *job-windows
diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md
index 2b1de43c2f6..20b6f7d10ef 100644
--- a/src/ci/docker/README.md
+++ b/src/ci/docker/README.md
@@ -8,15 +8,15 @@ Note that a single Docker image can be used by multiple CI jobs, so the job name
 is the important thing that you should know. You can examine the existing CI jobs in
 the [`jobs.yml`](../github-actions/jobs.yml) file.
 
-To run a specific CI job locally, you can use the following script:
+To run a specific CI job locally, you can use the `citool` Rust crate:
 
 ```
-python3 ./src/ci/github-actions/ci.py run-local <job-name>
+cargo run --manifest-path src/ci/citool/Cargo.toml run-local <job-name>
 ```
 
 For example, to run the `x86_64-gnu-llvm-18-1` job:
 ```
-python3 ./src/ci/github-actions/ci.py run-local x86_64-gnu-llvm-18-1
+cargo run --manifest-path src/ci/citool/Cargo.toml run-local x86_64-gnu-llvm-18-1
 ```
 
 The job will output artifacts in an `obj/<image-name>` dir at the root of a repository. Note
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
index 0b4682ac32b..f54ecef1e30 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
@@ -101,7 +101,7 @@ ENV SCRIPT python3 ../x.py build --set rust.debug=true opt-dist && \
     ./build/$HOSTS/stage0-tools-bin/opt-dist linux-ci -- python3 ../x.py dist \
     --host $HOSTS --target $HOSTS \
     --include-default-paths \
-    build-manifest bootstrap
+    build-manifest bootstrap gcc
 ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=clang
 
 # This is the only builder which will create source tarballs
diff --git a/src/ci/docker/scripts/rfl-build.sh b/src/ci/docker/scripts/rfl-build.sh
index 573821c3e59..ea8066d95e0 100755
--- a/src/ci/docker/scripts/rfl-build.sh
+++ b/src/ci/docker/scripts/rfl-build.sh
@@ -8,16 +8,10 @@ LINUX_VERSION=v6.14-rc3
 ../x.py build --stage 2 library rustdoc clippy rustfmt
 ../x.py build --stage 0 cargo
 
-# Install rustup so that we can use the built toolchain easily, and also
-# install bindgen in an easy way.
-curl --proto '=https' --tlsv1.2 -sSf -o rustup.sh https://sh.rustup.rs
-sh rustup.sh -y --default-toolchain none
+BUILD_DIR=$(realpath ./build/x86_64-unknown-linux-gnu)
 
-source /cargo/env
-
-BUILD_DIR=$(realpath ./build)
-rustup toolchain link local "${BUILD_DIR}"/x86_64-unknown-linux-gnu/stage2
-rustup default local
+# Provide path to rustc, rustdoc, clippy-driver and rustfmt to RfL
+export PATH=${PATH}:${BUILD_DIR}/stage2/bin
 
 mkdir -p rfl
 cd rfl
@@ -33,10 +27,14 @@ git -C linux fetch --depth 1 origin ${LINUX_VERSION}
 git -C linux checkout FETCH_HEAD
 
 # Install bindgen
-"${BUILD_DIR}"/x86_64-unknown-linux-gnu/stage0/bin/cargo install \
+"${BUILD_DIR}"/stage0/bin/cargo install \
   --version $(linux/scripts/min-tool-version.sh bindgen) \
+  --root ${BUILD_DIR}/bindgen \
   bindgen-cli
 
+# Provide path to bindgen to RfL
+export PATH=${PATH}:${BUILD_DIR}/bindgen/bin
+
 # Configure Rust for Linux
 cat <<EOF > linux/kernel/configs/rfl-for-rust-ci.config
 # CONFIG_WERROR is not set
diff --git a/src/ci/github-actions/ci.py b/src/ci/github-actions/ci.py
deleted file mode 100755
index c93766ef33a..00000000000
--- a/src/ci/github-actions/ci.py
+++ /dev/null
@@ -1,318 +0,0 @@
-#!/usr/bin/env python3
-
-"""
-This script contains CI functionality.
-It can be used to generate a matrix of jobs that should
-be executed on CI, or run a specific CI job locally.
-
-It reads job definitions from `src/ci/github-actions/jobs.yml`.
-"""
-
-import argparse
-import dataclasses
-import json
-import logging
-import os
-import re
-import subprocess
-import typing
-from pathlib import Path
-from typing import List, Dict, Any, Optional
-
-import yaml
-
-CI_DIR = Path(__file__).absolute().parent.parent
-JOBS_YAML_PATH = Path(__file__).absolute().parent / "jobs.yml"
-
-Job = Dict[str, Any]
-
-
-def add_job_properties(jobs: List[Dict], prefix: str) -> List[Job]:
-    """
-    Modify the `name` attribute of each job, based on its base name and the given `prefix`.
-    Add an `image` attribute to each job, based on its image.
-    """
-    modified_jobs = []
-    for job in jobs:
-        # Create a copy of the `job` dictionary to avoid modifying `jobs`
-        new_job = dict(job)
-        new_job["image"] = get_job_image(new_job)
-        new_job["full_name"] = f"{prefix} - {new_job['name']}"
-        modified_jobs.append(new_job)
-    return modified_jobs
-
-
-def add_base_env(jobs: List[Job], environment: Dict[str, str]) -> List[Job]:
-    """
-    Prepends `environment` to the `env` attribute of each job.
-    The `env` of each job has higher precedence than `environment`.
-    """
-    modified_jobs = []
-    for job in jobs:
-        env = environment.copy()
-        env.update(job.get("env", {}))
-
-        new_job = dict(job)
-        new_job["env"] = env
-        modified_jobs.append(new_job)
-    return modified_jobs
-
-
-@dataclasses.dataclass
-class PRRunType:
-    pass
-
-
-@dataclasses.dataclass
-class TryRunType:
-    custom_jobs: List[str]
-
-
-@dataclasses.dataclass
-class AutoRunType:
-    pass
-
-
-WorkflowRunType = typing.Union[PRRunType, TryRunType, AutoRunType]
-
-
-@dataclasses.dataclass
-class GitHubCtx:
-    event_name: str
-    ref: str
-    repository: str
-    commit_message: Optional[str]
-
-
-def get_custom_jobs(ctx: GitHubCtx) -> List[str]:
-    """
-    Tries to parse names of specific CI jobs that should be executed in the form of
-    try-job: <job-name>
-    from the commit message of the passed GitHub context.
-    """
-    if ctx.commit_message is None:
-        return []
-
-    regex = re.compile(r"^try-job: (.*)", re.MULTILINE)
-    jobs = []
-    for match in regex.finditer(ctx.commit_message):
-        jobs.append(match.group(1))
-    return jobs
-
-
-def find_run_type(ctx: GitHubCtx) -> Optional[WorkflowRunType]:
-    if ctx.event_name == "pull_request":
-        return PRRunType()
-    elif ctx.event_name == "push":
-        try_build = ctx.ref in (
-            "refs/heads/try",
-            "refs/heads/try-perf",
-            "refs/heads/automation/bors/try",
-        )
-
-        # Unrolled branch from a rollup for testing perf
-        # This should **not** allow custom try jobs
-        is_unrolled_perf_build = ctx.ref == "refs/heads/try-perf"
-
-        if try_build:
-            custom_jobs = []
-            if not is_unrolled_perf_build:
-                custom_jobs = get_custom_jobs(ctx)
-            return TryRunType(custom_jobs=custom_jobs)
-
-        if ctx.ref == "refs/heads/auto":
-            return AutoRunType()
-
-    return None
-
-
-def calculate_jobs(run_type: WorkflowRunType, job_data: Dict[str, Any]) -> List[Job]:
-    if isinstance(run_type, PRRunType):
-        return add_base_env(
-            add_job_properties(job_data["pr"], "PR"), job_data["envs"]["pr"]
-        )
-    elif isinstance(run_type, TryRunType):
-        jobs = job_data["try"]
-        custom_jobs = run_type.custom_jobs
-        if custom_jobs:
-            if len(custom_jobs) > 10:
-                raise Exception(
-                    f"It is only possible to schedule up to 10 custom jobs, "
-                    f"received {len(custom_jobs)} jobs"
-                )
-
-            jobs = []
-            unknown_jobs = []
-            for custom_job in custom_jobs:
-                job = [j for j in job_data["auto"] if j["name"] == custom_job]
-                if not job:
-                    unknown_jobs.append(custom_job)
-                    continue
-                jobs.append(job[0])
-            if unknown_jobs:
-                raise Exception(
-                    f"Custom job(s) `{unknown_jobs}` not found in auto jobs"
-                )
-
-        return add_base_env(add_job_properties(jobs, "try"), job_data["envs"]["try"])
-    elif isinstance(run_type, AutoRunType):
-        return add_base_env(
-            add_job_properties(job_data["auto"], "auto"), job_data["envs"]["auto"]
-        )
-
-    return []
-
-
-def skip_jobs(jobs: List[Dict[str, Any]], channel: str) -> List[Job]:
-    """
-    Skip CI jobs that are not supposed to be executed on the given `channel`.
-    """
-    return [j for j in jobs if j.get("only_on_channel", channel) == channel]
-
-
-def get_github_ctx() -> GitHubCtx:
-    event_name = os.environ["GITHUB_EVENT_NAME"]
-
-    commit_message = None
-    if event_name == "push":
-        commit_message = os.environ["COMMIT_MESSAGE"]
-    return GitHubCtx(
-        event_name=event_name,
-        ref=os.environ["GITHUB_REF"],
-        repository=os.environ["GITHUB_REPOSITORY"],
-        commit_message=commit_message,
-    )
-
-
-def format_run_type(run_type: WorkflowRunType) -> str:
-    if isinstance(run_type, PRRunType):
-        return "pr"
-    elif isinstance(run_type, AutoRunType):
-        return "auto"
-    elif isinstance(run_type, TryRunType):
-        return "try"
-    else:
-        raise AssertionError()
-
-
-def get_job_image(job: Job) -> str:
-    """
-    By default, the Docker image of a job is based on its name.
-    However, it can be overridden by its IMAGE environment variable.
-    """
-    env = job.get("env", {})
-    # Return the IMAGE environment variable if it exists, otherwise return the job name
-    return env.get("IMAGE", job["name"])
-
-
-def is_linux_job(job: Job) -> bool:
-    return "ubuntu" in job["os"]
-
-
-def find_linux_job(job_data: Dict[str, Any], job_name: str, pr_jobs: bool) -> Job:
-    candidates = job_data["pr"] if pr_jobs else job_data["auto"]
-    jobs = [job for job in candidates if job.get("name") == job_name]
-    if len(jobs) == 0:
-        available_jobs = "\n".join(
-            sorted(job["name"] for job in candidates if is_linux_job(job))
-        )
-        raise Exception(f"""Job `{job_name}` not found in {'pr' if pr_jobs else 'auto'} jobs.
-The following jobs are available:
-{available_jobs}""")
-    assert len(jobs) == 1
-
-    job = jobs[0]
-    if not is_linux_job(job):
-        raise Exception("Only Linux jobs can be executed locally")
-    return job
-
-
-def run_workflow_locally(job_data: Dict[str, Any], job_name: str, pr_jobs: bool):
-    DOCKER_DIR = Path(__file__).absolute().parent.parent / "docker"
-
-    job = find_linux_job(job_data, job_name=job_name, pr_jobs=pr_jobs)
-
-    custom_env = {}
-    # Replicate src/ci/scripts/setup-environment.sh
-    # Adds custom environment variables to the job
-    if job_name.startswith("dist-"):
-        if job_name.endswith("-alt"):
-            custom_env["DEPLOY_ALT"] = "1"
-        else:
-            custom_env["DEPLOY"] = "1"
-    custom_env.update({k: str(v) for (k, v) in job.get("env", {}).items()})
-
-    args = [str(DOCKER_DIR / "run.sh"), get_job_image(job)]
-    env_formatted = [f"{k}={v}" for (k, v) in sorted(custom_env.items())]
-    print(f"Executing `{' '.join(env_formatted)} {' '.join(args)}`")
-
-    env = os.environ.copy()
-    env.update(custom_env)
-
-    subprocess.run(args, env=env, check=True)
-
-
-def calculate_job_matrix(job_data: Dict[str, Any]):
-    github_ctx = get_github_ctx()
-
-    run_type = find_run_type(github_ctx)
-    logging.info(f"Job type: {run_type}")
-
-    with open(CI_DIR / "channel") as f:
-        channel = f.read().strip()
-
-    jobs = []
-    if run_type is not None:
-        jobs = calculate_jobs(run_type, job_data)
-    jobs = skip_jobs(jobs, channel)
-
-    if not jobs:
-        raise Exception("Scheduled job list is empty, this is an error")
-
-    run_type = format_run_type(run_type)
-
-    logging.info(f"Output:\n{yaml.dump(dict(jobs=jobs, run_type=run_type), indent=4)}")
-    print(f"jobs={json.dumps(jobs)}")
-    print(f"run_type={run_type}")
-
-
-def create_cli_parser():
-    parser = argparse.ArgumentParser(
-        prog="ci.py", description="Generate or run CI workflows"
-    )
-    subparsers = parser.add_subparsers(
-        help="Command to execute", dest="command", required=True
-    )
-    subparsers.add_parser(
-        "calculate-job-matrix",
-        help="Generate a matrix of jobs that should be executed in CI",
-    )
-    run_parser = subparsers.add_parser(
-        "run-local", help="Run a CI jobs locally (on Linux)"
-    )
-    run_parser.add_argument(
-        "job_name",
-        help="CI job that should be executed. By default, a merge (auto) "
-        "job with the given name will be executed",
-    )
-    run_parser.add_argument(
-        "--pr", action="store_true", help="Run a PR job instead of an auto job"
-    )
-    return parser
-
-
-if __name__ == "__main__":
-    logging.basicConfig(level=logging.INFO)
-
-    with open(JOBS_YAML_PATH) as f:
-        data = yaml.safe_load(f)
-
-    parser = create_cli_parser()
-    args = parser.parse_args()
-
-    if args.command == "calculate-job-matrix":
-        calculate_job_matrix(data)
-    elif args.command == "run-local":
-        run_workflow_locally(data, args.job_name, args.pr)
-    else:
-        raise Exception(f"Unknown command {args.command}")
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index 64e64867de2..bbcc01a0c29 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -51,9 +51,11 @@ runners:
     # Free some disk space to avoid running out of space during the build.
     free_disk: true
     os: ubuntu-24.04-arm
+    <<: *base-job
 
   - &job-aarch64-linux-8c
     os: ubuntu-22.04-arm64-8core-32gb
+    <<: *base-job
 envs:
   env-x86_64-apple-tests: &env-x86_64-apple-tests
     SCRIPT: ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc -- --exact
diff --git a/src/ci/package-lock.json b/src/ci/package-lock.json
deleted file mode 100644
index 6bbdc6adcfd..00000000000
--- a/src/ci/package-lock.json
+++ /dev/null
@@ -1,5004 +0,0 @@
-{
-  "name": "ci",
-  "lockfileVersion": 3,
-  "requires": true,
-  "packages": {
-    "": {
-      "dependencies": {
-        "@datadog/datadog-ci": "^2.45.1"
-      }
-    },
-    "node_modules/@aws-crypto/crc32": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz",
-      "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-crypto/util": "^5.2.0",
-        "@aws-sdk/types": "^3.222.0",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-crypto/sha256-browser": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz",
-      "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-crypto/sha256-js": "^5.2.0",
-        "@aws-crypto/supports-web-crypto": "^5.2.0",
-        "@aws-crypto/util": "^5.2.0",
-        "@aws-sdk/types": "^3.222.0",
-        "@aws-sdk/util-locate-window": "^3.0.0",
-        "@smithy/util-utf8": "^2.0.0",
-        "tslib": "^2.6.2"
-      }
-    },
-    "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz",
-      "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=14.0.0"
-      }
-    },
-    "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz",
-      "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/is-array-buffer": "^2.2.0",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=14.0.0"
-      }
-    },
-    "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
-      "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/util-buffer-from": "^2.2.0",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=14.0.0"
-      }
-    },
-    "node_modules/@aws-crypto/sha256-js": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz",
-      "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-crypto/util": "^5.2.0",
-        "@aws-sdk/types": "^3.222.0",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-crypto/supports-web-crypto": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz",
-      "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "tslib": "^2.6.2"
-      }
-    },
-    "node_modules/@aws-crypto/util": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz",
-      "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-sdk/types": "^3.222.0",
-        "@smithy/util-utf8": "^2.0.0",
-        "tslib": "^2.6.2"
-      }
-    },
-    "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz",
-      "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=14.0.0"
-      }
-    },
-    "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz",
-      "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/is-array-buffer": "^2.2.0",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=14.0.0"
-      }
-    },
-    "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
-      "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/util-buffer-from": "^2.2.0",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=14.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/client-cloudwatch-logs": {
-      "version": "3.703.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudwatch-logs/-/client-cloudwatch-logs-3.703.0.tgz",
-      "integrity": "sha512-KkLMwrNhkLZr3OCRWakJY16OF8pUZCoexxZkWzHfR/Pw3WBcDtBMEiEO13P6oHlGAn1VvIDxxMBSxeg/89xyJA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-crypto/sha256-browser": "5.2.0",
-        "@aws-crypto/sha256-js": "5.2.0",
-        "@aws-sdk/client-sso-oidc": "3.699.0",
-        "@aws-sdk/client-sts": "3.699.0",
-        "@aws-sdk/core": "3.696.0",
-        "@aws-sdk/credential-provider-node": "3.699.0",
-        "@aws-sdk/middleware-host-header": "3.696.0",
-        "@aws-sdk/middleware-logger": "3.696.0",
-        "@aws-sdk/middleware-recursion-detection": "3.696.0",
-        "@aws-sdk/middleware-user-agent": "3.696.0",
-        "@aws-sdk/region-config-resolver": "3.696.0",
-        "@aws-sdk/types": "3.696.0",
-        "@aws-sdk/util-endpoints": "3.696.0",
-        "@aws-sdk/util-user-agent-browser": "3.696.0",
-        "@aws-sdk/util-user-agent-node": "3.696.0",
-        "@smithy/config-resolver": "^3.0.12",
-        "@smithy/core": "^2.5.3",
-        "@smithy/eventstream-serde-browser": "^3.0.13",
-        "@smithy/eventstream-serde-config-resolver": "^3.0.10",
-        "@smithy/eventstream-serde-node": "^3.0.12",
-        "@smithy/fetch-http-handler": "^4.1.1",
-        "@smithy/hash-node": "^3.0.10",
-        "@smithy/invalid-dependency": "^3.0.10",
-        "@smithy/middleware-content-length": "^3.0.12",
-        "@smithy/middleware-endpoint": "^3.2.3",
-        "@smithy/middleware-retry": "^3.0.27",
-        "@smithy/middleware-serde": "^3.0.10",
-        "@smithy/middleware-stack": "^3.0.10",
-        "@smithy/node-config-provider": "^3.1.11",
-        "@smithy/node-http-handler": "^3.3.1",
-        "@smithy/protocol-http": "^4.1.7",
-        "@smithy/smithy-client": "^3.4.4",
-        "@smithy/types": "^3.7.1",
-        "@smithy/url-parser": "^3.0.10",
-        "@smithy/util-base64": "^3.0.0",
-        "@smithy/util-body-length-browser": "^3.0.0",
-        "@smithy/util-body-length-node": "^3.0.0",
-        "@smithy/util-defaults-mode-browser": "^3.0.27",
-        "@smithy/util-defaults-mode-node": "^3.0.27",
-        "@smithy/util-endpoints": "^2.1.6",
-        "@smithy/util-middleware": "^3.0.10",
-        "@smithy/util-retry": "^3.0.10",
-        "@smithy/util-utf8": "^3.0.0",
-        "@types/uuid": "^9.0.1",
-        "tslib": "^2.6.2",
-        "uuid": "^9.0.1"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/util-retry": {
-      "version": "3.0.11",
-      "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.11.tgz",
-      "integrity": "sha512-hJUC6W7A3DQgaee3Hp9ZFcOxVDZzmBIRBPlUAk8/fSOEl7pE/aX7Dci0JycNOnm9Mfr0KV2XjIlUOcGWXQUdVQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/service-error-classification": "^3.0.11",
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/client-cognito-identity": {
-      "version": "3.699.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.699.0.tgz",
-      "integrity": "sha512-9tFt+we6AIvj/f1+nrLHuCWcQmyfux5gcBSOy9d9+zIG56YxGEX7S9TaZnybogpVV8A0BYWml36WvIHS9QjIpA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-crypto/sha256-browser": "5.2.0",
-        "@aws-crypto/sha256-js": "5.2.0",
-        "@aws-sdk/client-sso-oidc": "3.699.0",
-        "@aws-sdk/client-sts": "3.699.0",
-        "@aws-sdk/core": "3.696.0",
-        "@aws-sdk/credential-provider-node": "3.699.0",
-        "@aws-sdk/middleware-host-header": "3.696.0",
-        "@aws-sdk/middleware-logger": "3.696.0",
-        "@aws-sdk/middleware-recursion-detection": "3.696.0",
-        "@aws-sdk/middleware-user-agent": "3.696.0",
-        "@aws-sdk/region-config-resolver": "3.696.0",
-        "@aws-sdk/types": "3.696.0",
-        "@aws-sdk/util-endpoints": "3.696.0",
-        "@aws-sdk/util-user-agent-browser": "3.696.0",
-        "@aws-sdk/util-user-agent-node": "3.696.0",
-        "@smithy/config-resolver": "^3.0.12",
-        "@smithy/core": "^2.5.3",
-        "@smithy/fetch-http-handler": "^4.1.1",
-        "@smithy/hash-node": "^3.0.10",
-        "@smithy/invalid-dependency": "^3.0.10",
-        "@smithy/middleware-content-length": "^3.0.12",
-        "@smithy/middleware-endpoint": "^3.2.3",
-        "@smithy/middleware-retry": "^3.0.27",
-        "@smithy/middleware-serde": "^3.0.10",
-        "@smithy/middleware-stack": "^3.0.10",
-        "@smithy/node-config-provider": "^3.1.11",
-        "@smithy/node-http-handler": "^3.3.1",
-        "@smithy/protocol-http": "^4.1.7",
-        "@smithy/smithy-client": "^3.4.4",
-        "@smithy/types": "^3.7.1",
-        "@smithy/url-parser": "^3.0.10",
-        "@smithy/util-base64": "^3.0.0",
-        "@smithy/util-body-length-browser": "^3.0.0",
-        "@smithy/util-body-length-node": "^3.0.0",
-        "@smithy/util-defaults-mode-browser": "^3.0.27",
-        "@smithy/util-defaults-mode-node": "^3.0.27",
-        "@smithy/util-endpoints": "^2.1.6",
-        "@smithy/util-middleware": "^3.0.10",
-        "@smithy/util-retry": "^3.0.10",
-        "@smithy/util-utf8": "^3.0.0",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/client-cognito-identity/node_modules/@smithy/util-retry": {
-      "version": "3.0.11",
-      "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.11.tgz",
-      "integrity": "sha512-hJUC6W7A3DQgaee3Hp9ZFcOxVDZzmBIRBPlUAk8/fSOEl7pE/aX7Dci0JycNOnm9Mfr0KV2XjIlUOcGWXQUdVQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/service-error-classification": "^3.0.11",
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/client-iam": {
-      "version": "3.699.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/client-iam/-/client-iam-3.699.0.tgz",
-      "integrity": "sha512-JBVcmkGaV7tW/mEntqt6KdkhsyYU2oIMUbkNHJextKqu6odSkuB1mN70TgctwFP8x2LDgFzvT6WcWVCKc/g3Ng==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-crypto/sha256-browser": "5.2.0",
-        "@aws-crypto/sha256-js": "5.2.0",
-        "@aws-sdk/client-sso-oidc": "3.699.0",
-        "@aws-sdk/client-sts": "3.699.0",
-        "@aws-sdk/core": "3.696.0",
-        "@aws-sdk/credential-provider-node": "3.699.0",
-        "@aws-sdk/middleware-host-header": "3.696.0",
-        "@aws-sdk/middleware-logger": "3.696.0",
-        "@aws-sdk/middleware-recursion-detection": "3.696.0",
-        "@aws-sdk/middleware-user-agent": "3.696.0",
-        "@aws-sdk/region-config-resolver": "3.696.0",
-        "@aws-sdk/types": "3.696.0",
-        "@aws-sdk/util-endpoints": "3.696.0",
-        "@aws-sdk/util-user-agent-browser": "3.696.0",
-        "@aws-sdk/util-user-agent-node": "3.696.0",
-        "@smithy/config-resolver": "^3.0.12",
-        "@smithy/core": "^2.5.3",
-        "@smithy/fetch-http-handler": "^4.1.1",
-        "@smithy/hash-node": "^3.0.10",
-        "@smithy/invalid-dependency": "^3.0.10",
-        "@smithy/middleware-content-length": "^3.0.12",
-        "@smithy/middleware-endpoint": "^3.2.3",
-        "@smithy/middleware-retry": "^3.0.27",
-        "@smithy/middleware-serde": "^3.0.10",
-        "@smithy/middleware-stack": "^3.0.10",
-        "@smithy/node-config-provider": "^3.1.11",
-        "@smithy/node-http-handler": "^3.3.1",
-        "@smithy/protocol-http": "^4.1.7",
-        "@smithy/smithy-client": "^3.4.4",
-        "@smithy/types": "^3.7.1",
-        "@smithy/url-parser": "^3.0.10",
-        "@smithy/util-base64": "^3.0.0",
-        "@smithy/util-body-length-browser": "^3.0.0",
-        "@smithy/util-body-length-node": "^3.0.0",
-        "@smithy/util-defaults-mode-browser": "^3.0.27",
-        "@smithy/util-defaults-mode-node": "^3.0.27",
-        "@smithy/util-endpoints": "^2.1.6",
-        "@smithy/util-middleware": "^3.0.10",
-        "@smithy/util-retry": "^3.0.10",
-        "@smithy/util-utf8": "^3.0.0",
-        "@smithy/util-waiter": "^3.1.9",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/client-iam/node_modules/@smithy/util-retry": {
-      "version": "3.0.11",
-      "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.11.tgz",
-      "integrity": "sha512-hJUC6W7A3DQgaee3Hp9ZFcOxVDZzmBIRBPlUAk8/fSOEl7pE/aX7Dci0JycNOnm9Mfr0KV2XjIlUOcGWXQUdVQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/service-error-classification": "^3.0.11",
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/client-lambda": {
-      "version": "3.699.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/client-lambda/-/client-lambda-3.699.0.tgz",
-      "integrity": "sha512-K9TGvQB8hkjwNhfWSfYllUpttqxTcd78ShSRCIhlcwzzsmQphET10xEb0Tm1k8sqriSQ+CiVOFSkX78gqoHzBg==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-crypto/sha256-browser": "5.2.0",
-        "@aws-crypto/sha256-js": "5.2.0",
-        "@aws-sdk/client-sso-oidc": "3.699.0",
-        "@aws-sdk/client-sts": "3.699.0",
-        "@aws-sdk/core": "3.696.0",
-        "@aws-sdk/credential-provider-node": "3.699.0",
-        "@aws-sdk/middleware-host-header": "3.696.0",
-        "@aws-sdk/middleware-logger": "3.696.0",
-        "@aws-sdk/middleware-recursion-detection": "3.696.0",
-        "@aws-sdk/middleware-user-agent": "3.696.0",
-        "@aws-sdk/region-config-resolver": "3.696.0",
-        "@aws-sdk/types": "3.696.0",
-        "@aws-sdk/util-endpoints": "3.696.0",
-        "@aws-sdk/util-user-agent-browser": "3.696.0",
-        "@aws-sdk/util-user-agent-node": "3.696.0",
-        "@smithy/config-resolver": "^3.0.12",
-        "@smithy/core": "^2.5.3",
-        "@smithy/eventstream-serde-browser": "^3.0.13",
-        "@smithy/eventstream-serde-config-resolver": "^3.0.10",
-        "@smithy/eventstream-serde-node": "^3.0.12",
-        "@smithy/fetch-http-handler": "^4.1.1",
-        "@smithy/hash-node": "^3.0.10",
-        "@smithy/invalid-dependency": "^3.0.10",
-        "@smithy/middleware-content-length": "^3.0.12",
-        "@smithy/middleware-endpoint": "^3.2.3",
-        "@smithy/middleware-retry": "^3.0.27",
-        "@smithy/middleware-serde": "^3.0.10",
-        "@smithy/middleware-stack": "^3.0.10",
-        "@smithy/node-config-provider": "^3.1.11",
-        "@smithy/node-http-handler": "^3.3.1",
-        "@smithy/protocol-http": "^4.1.7",
-        "@smithy/smithy-client": "^3.4.4",
-        "@smithy/types": "^3.7.1",
-        "@smithy/url-parser": "^3.0.10",
-        "@smithy/util-base64": "^3.0.0",
-        "@smithy/util-body-length-browser": "^3.0.0",
-        "@smithy/util-body-length-node": "^3.0.0",
-        "@smithy/util-defaults-mode-browser": "^3.0.27",
-        "@smithy/util-defaults-mode-node": "^3.0.27",
-        "@smithy/util-endpoints": "^2.1.6",
-        "@smithy/util-middleware": "^3.0.10",
-        "@smithy/util-retry": "^3.0.10",
-        "@smithy/util-stream": "^3.3.1",
-        "@smithy/util-utf8": "^3.0.0",
-        "@smithy/util-waiter": "^3.1.9",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/client-lambda/node_modules/@smithy/util-retry": {
-      "version": "3.0.11",
-      "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.11.tgz",
-      "integrity": "sha512-hJUC6W7A3DQgaee3Hp9ZFcOxVDZzmBIRBPlUAk8/fSOEl7pE/aX7Dci0JycNOnm9Mfr0KV2XjIlUOcGWXQUdVQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/service-error-classification": "^3.0.11",
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/client-sfn": {
-      "version": "3.699.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/client-sfn/-/client-sfn-3.699.0.tgz",
-      "integrity": "sha512-66/+rOMVvjKRhKDDsrxtfRzXXsAfVu/RbhxPYepcVhO+0/ii6DL2uQCeNhMN3+MPg+HWX695H5RyBVJ6QGli8w==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-crypto/sha256-browser": "5.2.0",
-        "@aws-crypto/sha256-js": "5.2.0",
-        "@aws-sdk/client-sso-oidc": "3.699.0",
-        "@aws-sdk/client-sts": "3.699.0",
-        "@aws-sdk/core": "3.696.0",
-        "@aws-sdk/credential-provider-node": "3.699.0",
-        "@aws-sdk/middleware-host-header": "3.696.0",
-        "@aws-sdk/middleware-logger": "3.696.0",
-        "@aws-sdk/middleware-recursion-detection": "3.696.0",
-        "@aws-sdk/middleware-user-agent": "3.696.0",
-        "@aws-sdk/region-config-resolver": "3.696.0",
-        "@aws-sdk/types": "3.696.0",
-        "@aws-sdk/util-endpoints": "3.696.0",
-        "@aws-sdk/util-user-agent-browser": "3.696.0",
-        "@aws-sdk/util-user-agent-node": "3.696.0",
-        "@smithy/config-resolver": "^3.0.12",
-        "@smithy/core": "^2.5.3",
-        "@smithy/fetch-http-handler": "^4.1.1",
-        "@smithy/hash-node": "^3.0.10",
-        "@smithy/invalid-dependency": "^3.0.10",
-        "@smithy/middleware-content-length": "^3.0.12",
-        "@smithy/middleware-endpoint": "^3.2.3",
-        "@smithy/middleware-retry": "^3.0.27",
-        "@smithy/middleware-serde": "^3.0.10",
-        "@smithy/middleware-stack": "^3.0.10",
-        "@smithy/node-config-provider": "^3.1.11",
-        "@smithy/node-http-handler": "^3.3.1",
-        "@smithy/protocol-http": "^4.1.7",
-        "@smithy/smithy-client": "^3.4.4",
-        "@smithy/types": "^3.7.1",
-        "@smithy/url-parser": "^3.0.10",
-        "@smithy/util-base64": "^3.0.0",
-        "@smithy/util-body-length-browser": "^3.0.0",
-        "@smithy/util-body-length-node": "^3.0.0",
-        "@smithy/util-defaults-mode-browser": "^3.0.27",
-        "@smithy/util-defaults-mode-node": "^3.0.27",
-        "@smithy/util-endpoints": "^2.1.6",
-        "@smithy/util-middleware": "^3.0.10",
-        "@smithy/util-retry": "^3.0.10",
-        "@smithy/util-utf8": "^3.0.0",
-        "@types/uuid": "^9.0.1",
-        "tslib": "^2.6.2",
-        "uuid": "^9.0.1"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/client-sfn/node_modules/@smithy/util-retry": {
-      "version": "3.0.11",
-      "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.11.tgz",
-      "integrity": "sha512-hJUC6W7A3DQgaee3Hp9ZFcOxVDZzmBIRBPlUAk8/fSOEl7pE/aX7Dci0JycNOnm9Mfr0KV2XjIlUOcGWXQUdVQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/service-error-classification": "^3.0.11",
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/client-sso": {
-      "version": "3.696.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.696.0.tgz",
-      "integrity": "sha512-q5TTkd08JS0DOkHfUL853tuArf7NrPeqoS5UOvqJho8ibV9Ak/a/HO4kNvy9Nj3cib/toHYHsQIEtecUPSUUrQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-crypto/sha256-browser": "5.2.0",
-        "@aws-crypto/sha256-js": "5.2.0",
-        "@aws-sdk/core": "3.696.0",
-        "@aws-sdk/middleware-host-header": "3.696.0",
-        "@aws-sdk/middleware-logger": "3.696.0",
-        "@aws-sdk/middleware-recursion-detection": "3.696.0",
-        "@aws-sdk/middleware-user-agent": "3.696.0",
-        "@aws-sdk/region-config-resolver": "3.696.0",
-        "@aws-sdk/types": "3.696.0",
-        "@aws-sdk/util-endpoints": "3.696.0",
-        "@aws-sdk/util-user-agent-browser": "3.696.0",
-        "@aws-sdk/util-user-agent-node": "3.696.0",
-        "@smithy/config-resolver": "^3.0.12",
-        "@smithy/core": "^2.5.3",
-        "@smithy/fetch-http-handler": "^4.1.1",
-        "@smithy/hash-node": "^3.0.10",
-        "@smithy/invalid-dependency": "^3.0.10",
-        "@smithy/middleware-content-length": "^3.0.12",
-        "@smithy/middleware-endpoint": "^3.2.3",
-        "@smithy/middleware-retry": "^3.0.27",
-        "@smithy/middleware-serde": "^3.0.10",
-        "@smithy/middleware-stack": "^3.0.10",
-        "@smithy/node-config-provider": "^3.1.11",
-        "@smithy/node-http-handler": "^3.3.1",
-        "@smithy/protocol-http": "^4.1.7",
-        "@smithy/smithy-client": "^3.4.4",
-        "@smithy/types": "^3.7.1",
-        "@smithy/url-parser": "^3.0.10",
-        "@smithy/util-base64": "^3.0.0",
-        "@smithy/util-body-length-browser": "^3.0.0",
-        "@smithy/util-body-length-node": "^3.0.0",
-        "@smithy/util-defaults-mode-browser": "^3.0.27",
-        "@smithy/util-defaults-mode-node": "^3.0.27",
-        "@smithy/util-endpoints": "^2.1.6",
-        "@smithy/util-middleware": "^3.0.10",
-        "@smithy/util-retry": "^3.0.10",
-        "@smithy/util-utf8": "^3.0.0",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/client-sso-oidc": {
-      "version": "3.699.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.699.0.tgz",
-      "integrity": "sha512-u8a1GorY5D1l+4FQAf4XBUC1T10/t7neuwT21r0ymrtMFSK2a9QqVHKMoLkvavAwyhJnARSBM9/UQC797PFOFw==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-crypto/sha256-browser": "5.2.0",
-        "@aws-crypto/sha256-js": "5.2.0",
-        "@aws-sdk/core": "3.696.0",
-        "@aws-sdk/credential-provider-node": "3.699.0",
-        "@aws-sdk/middleware-host-header": "3.696.0",
-        "@aws-sdk/middleware-logger": "3.696.0",
-        "@aws-sdk/middleware-recursion-detection": "3.696.0",
-        "@aws-sdk/middleware-user-agent": "3.696.0",
-        "@aws-sdk/region-config-resolver": "3.696.0",
-        "@aws-sdk/types": "3.696.0",
-        "@aws-sdk/util-endpoints": "3.696.0",
-        "@aws-sdk/util-user-agent-browser": "3.696.0",
-        "@aws-sdk/util-user-agent-node": "3.696.0",
-        "@smithy/config-resolver": "^3.0.12",
-        "@smithy/core": "^2.5.3",
-        "@smithy/fetch-http-handler": "^4.1.1",
-        "@smithy/hash-node": "^3.0.10",
-        "@smithy/invalid-dependency": "^3.0.10",
-        "@smithy/middleware-content-length": "^3.0.12",
-        "@smithy/middleware-endpoint": "^3.2.3",
-        "@smithy/middleware-retry": "^3.0.27",
-        "@smithy/middleware-serde": "^3.0.10",
-        "@smithy/middleware-stack": "^3.0.10",
-        "@smithy/node-config-provider": "^3.1.11",
-        "@smithy/node-http-handler": "^3.3.1",
-        "@smithy/protocol-http": "^4.1.7",
-        "@smithy/smithy-client": "^3.4.4",
-        "@smithy/types": "^3.7.1",
-        "@smithy/url-parser": "^3.0.10",
-        "@smithy/util-base64": "^3.0.0",
-        "@smithy/util-body-length-browser": "^3.0.0",
-        "@smithy/util-body-length-node": "^3.0.0",
-        "@smithy/util-defaults-mode-browser": "^3.0.27",
-        "@smithy/util-defaults-mode-node": "^3.0.27",
-        "@smithy/util-endpoints": "^2.1.6",
-        "@smithy/util-middleware": "^3.0.10",
-        "@smithy/util-retry": "^3.0.10",
-        "@smithy/util-utf8": "^3.0.0",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      },
-      "peerDependencies": {
-        "@aws-sdk/client-sts": "^3.699.0"
-      }
-    },
-    "node_modules/@aws-sdk/client-sso-oidc/node_modules/@smithy/util-retry": {
-      "version": "3.0.11",
-      "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.11.tgz",
-      "integrity": "sha512-hJUC6W7A3DQgaee3Hp9ZFcOxVDZzmBIRBPlUAk8/fSOEl7pE/aX7Dci0JycNOnm9Mfr0KV2XjIlUOcGWXQUdVQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/service-error-classification": "^3.0.11",
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/client-sso/node_modules/@smithy/util-retry": {
-      "version": "3.0.11",
-      "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.11.tgz",
-      "integrity": "sha512-hJUC6W7A3DQgaee3Hp9ZFcOxVDZzmBIRBPlUAk8/fSOEl7pE/aX7Dci0JycNOnm9Mfr0KV2XjIlUOcGWXQUdVQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/service-error-classification": "^3.0.11",
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/client-sts": {
-      "version": "3.699.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.699.0.tgz",
-      "integrity": "sha512-++lsn4x2YXsZPIzFVwv3fSUVM55ZT0WRFmPeNilYIhZClxHLmVAWKH4I55cY9ry60/aTKYjzOXkWwyBKGsGvQg==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-crypto/sha256-browser": "5.2.0",
-        "@aws-crypto/sha256-js": "5.2.0",
-        "@aws-sdk/client-sso-oidc": "3.699.0",
-        "@aws-sdk/core": "3.696.0",
-        "@aws-sdk/credential-provider-node": "3.699.0",
-        "@aws-sdk/middleware-host-header": "3.696.0",
-        "@aws-sdk/middleware-logger": "3.696.0",
-        "@aws-sdk/middleware-recursion-detection": "3.696.0",
-        "@aws-sdk/middleware-user-agent": "3.696.0",
-        "@aws-sdk/region-config-resolver": "3.696.0",
-        "@aws-sdk/types": "3.696.0",
-        "@aws-sdk/util-endpoints": "3.696.0",
-        "@aws-sdk/util-user-agent-browser": "3.696.0",
-        "@aws-sdk/util-user-agent-node": "3.696.0",
-        "@smithy/config-resolver": "^3.0.12",
-        "@smithy/core": "^2.5.3",
-        "@smithy/fetch-http-handler": "^4.1.1",
-        "@smithy/hash-node": "^3.0.10",
-        "@smithy/invalid-dependency": "^3.0.10",
-        "@smithy/middleware-content-length": "^3.0.12",
-        "@smithy/middleware-endpoint": "^3.2.3",
-        "@smithy/middleware-retry": "^3.0.27",
-        "@smithy/middleware-serde": "^3.0.10",
-        "@smithy/middleware-stack": "^3.0.10",
-        "@smithy/node-config-provider": "^3.1.11",
-        "@smithy/node-http-handler": "^3.3.1",
-        "@smithy/protocol-http": "^4.1.7",
-        "@smithy/smithy-client": "^3.4.4",
-        "@smithy/types": "^3.7.1",
-        "@smithy/url-parser": "^3.0.10",
-        "@smithy/util-base64": "^3.0.0",
-        "@smithy/util-body-length-browser": "^3.0.0",
-        "@smithy/util-body-length-node": "^3.0.0",
-        "@smithy/util-defaults-mode-browser": "^3.0.27",
-        "@smithy/util-defaults-mode-node": "^3.0.27",
-        "@smithy/util-endpoints": "^2.1.6",
-        "@smithy/util-middleware": "^3.0.10",
-        "@smithy/util-retry": "^3.0.10",
-        "@smithy/util-utf8": "^3.0.0",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/client-sts/node_modules/@smithy/util-retry": {
-      "version": "3.0.11",
-      "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.11.tgz",
-      "integrity": "sha512-hJUC6W7A3DQgaee3Hp9ZFcOxVDZzmBIRBPlUAk8/fSOEl7pE/aX7Dci0JycNOnm9Mfr0KV2XjIlUOcGWXQUdVQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/service-error-classification": "^3.0.11",
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/core": {
-      "version": "3.696.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.696.0.tgz",
-      "integrity": "sha512-3c9III1k03DgvRZWg8vhVmfIXPG6hAciN9MzQTzqGngzWAELZF/WONRTRQuDFixVtarQatmLHYVw/atGeA2Byw==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-sdk/types": "3.696.0",
-        "@smithy/core": "^2.5.3",
-        "@smithy/node-config-provider": "^3.1.11",
-        "@smithy/property-provider": "^3.1.9",
-        "@smithy/protocol-http": "^4.1.7",
-        "@smithy/signature-v4": "^4.2.2",
-        "@smithy/smithy-client": "^3.4.4",
-        "@smithy/types": "^3.7.1",
-        "@smithy/util-middleware": "^3.0.10",
-        "fast-xml-parser": "4.4.1",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/core/node_modules/@smithy/property-provider": {
-      "version": "3.1.11",
-      "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.11.tgz",
-      "integrity": "sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/core/node_modules/fast-xml-parser": {
-      "version": "4.4.1",
-      "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz",
-      "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==",
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/NaturalIntelligence"
-        },
-        {
-          "type": "paypal",
-          "url": "https://paypal.me/naturalintelligence"
-        }
-      ],
-      "license": "MIT",
-      "dependencies": {
-        "strnum": "^1.0.5"
-      },
-      "bin": {
-        "fxparser": "src/cli/cli.js"
-      }
-    },
-    "node_modules/@aws-sdk/credential-provider-cognito-identity": {
-      "version": "3.699.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.699.0.tgz",
-      "integrity": "sha512-iuaTnudaBfEET+o444sDwf71Awe6UiZfH+ipUPmswAi2jZDwdFF1nxMKDEKL8/LV5WpXsdKSfwgS0RQeupURew==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-sdk/client-cognito-identity": "3.699.0",
-        "@aws-sdk/types": "3.696.0",
-        "@smithy/property-provider": "^3.1.9",
-        "@smithy/types": "^3.7.1",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/credential-provider-cognito-identity/node_modules/@smithy/property-provider": {
-      "version": "3.1.11",
-      "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.11.tgz",
-      "integrity": "sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/credential-provider-env": {
-      "version": "3.696.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.696.0.tgz",
-      "integrity": "sha512-T9iMFnJL7YTlESLpVFT3fg1Lkb1lD+oiaIC8KMpepb01gDUBIpj9+Y+pA/cgRWW0yRxmkDXNazAE2qQTVFGJzA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-sdk/core": "3.696.0",
-        "@aws-sdk/types": "3.696.0",
-        "@smithy/property-provider": "^3.1.9",
-        "@smithy/types": "^3.7.1",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/credential-provider-env/node_modules/@smithy/property-provider": {
-      "version": "3.1.11",
-      "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.11.tgz",
-      "integrity": "sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/credential-provider-http": {
-      "version": "3.696.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.696.0.tgz",
-      "integrity": "sha512-GV6EbvPi2eq1+WgY/o2RFA3P7HGmnkIzCNmhwtALFlqMroLYWKE7PSeHw66Uh1dFQeVESn0/+hiUNhu1mB0emA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-sdk/core": "3.696.0",
-        "@aws-sdk/types": "3.696.0",
-        "@smithy/fetch-http-handler": "^4.1.1",
-        "@smithy/node-http-handler": "^3.3.1",
-        "@smithy/property-provider": "^3.1.9",
-        "@smithy/protocol-http": "^4.1.7",
-        "@smithy/smithy-client": "^3.4.4",
-        "@smithy/types": "^3.7.1",
-        "@smithy/util-stream": "^3.3.1",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/credential-provider-http/node_modules/@smithy/property-provider": {
-      "version": "3.1.11",
-      "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.11.tgz",
-      "integrity": "sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/credential-provider-ini": {
-      "version": "3.699.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.699.0.tgz",
-      "integrity": "sha512-dXmCqjJnKmG37Q+nLjPVu22mNkrGHY8hYoOt3Jo9R2zr5MYV7s/NHsCHr+7E+BZ+tfZYLRPeB1wkpTeHiEcdRw==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-sdk/core": "3.696.0",
-        "@aws-sdk/credential-provider-env": "3.696.0",
-        "@aws-sdk/credential-provider-http": "3.696.0",
-        "@aws-sdk/credential-provider-process": "3.696.0",
-        "@aws-sdk/credential-provider-sso": "3.699.0",
-        "@aws-sdk/credential-provider-web-identity": "3.696.0",
-        "@aws-sdk/types": "3.696.0",
-        "@smithy/credential-provider-imds": "^3.2.6",
-        "@smithy/property-provider": "^3.1.9",
-        "@smithy/shared-ini-file-loader": "^3.1.10",
-        "@smithy/types": "^3.7.1",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      },
-      "peerDependencies": {
-        "@aws-sdk/client-sts": "^3.699.0"
-      }
-    },
-    "node_modules/@aws-sdk/credential-provider-ini/node_modules/@smithy/property-provider": {
-      "version": "3.1.11",
-      "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.11.tgz",
-      "integrity": "sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/credential-provider-node": {
-      "version": "3.699.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.699.0.tgz",
-      "integrity": "sha512-MmEmNDo1bBtTgRmdNfdQksXu4uXe66s0p1hi1YPrn1h59Q605eq/xiWbGL6/3KdkViH6eGUuABeV2ODld86ylg==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-sdk/credential-provider-env": "3.696.0",
-        "@aws-sdk/credential-provider-http": "3.696.0",
-        "@aws-sdk/credential-provider-ini": "3.699.0",
-        "@aws-sdk/credential-provider-process": "3.696.0",
-        "@aws-sdk/credential-provider-sso": "3.699.0",
-        "@aws-sdk/credential-provider-web-identity": "3.696.0",
-        "@aws-sdk/types": "3.696.0",
-        "@smithy/credential-provider-imds": "^3.2.6",
-        "@smithy/property-provider": "^3.1.9",
-        "@smithy/shared-ini-file-loader": "^3.1.10",
-        "@smithy/types": "^3.7.1",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/credential-provider-node/node_modules/@smithy/property-provider": {
-      "version": "3.1.11",
-      "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.11.tgz",
-      "integrity": "sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/credential-provider-process": {
-      "version": "3.696.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.696.0.tgz",
-      "integrity": "sha512-mL1RcFDe9sfmyU5K1nuFkO8UiJXXxLX4JO1gVaDIOvPqwStpUAwi3A1BoeZhWZZNQsiKI810RnYGo0E0WB/hUA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-sdk/core": "3.696.0",
-        "@aws-sdk/types": "3.696.0",
-        "@smithy/property-provider": "^3.1.9",
-        "@smithy/shared-ini-file-loader": "^3.1.10",
-        "@smithy/types": "^3.7.1",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/credential-provider-process/node_modules/@smithy/property-provider": {
-      "version": "3.1.11",
-      "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.11.tgz",
-      "integrity": "sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/credential-provider-sso": {
-      "version": "3.699.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.699.0.tgz",
-      "integrity": "sha512-Ekp2cZG4pl9D8+uKWm4qO1xcm8/MeiI8f+dnlZm8aQzizeC+aXYy9GyoclSf6daK8KfRPiRfM7ZHBBL5dAfdMA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-sdk/client-sso": "3.696.0",
-        "@aws-sdk/core": "3.696.0",
-        "@aws-sdk/token-providers": "3.699.0",
-        "@aws-sdk/types": "3.696.0",
-        "@smithy/property-provider": "^3.1.9",
-        "@smithy/shared-ini-file-loader": "^3.1.10",
-        "@smithy/types": "^3.7.1",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/credential-provider-sso/node_modules/@smithy/property-provider": {
-      "version": "3.1.11",
-      "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.11.tgz",
-      "integrity": "sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/credential-provider-web-identity": {
-      "version": "3.696.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.696.0.tgz",
-      "integrity": "sha512-XJ/CVlWChM0VCoc259vWguFUjJDn/QwDqHwbx+K9cg3v6yrqXfK5ai+p/6lx0nQpnk4JzPVeYYxWRpaTsGC9rg==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-sdk/core": "3.696.0",
-        "@aws-sdk/types": "3.696.0",
-        "@smithy/property-provider": "^3.1.9",
-        "@smithy/types": "^3.7.1",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      },
-      "peerDependencies": {
-        "@aws-sdk/client-sts": "^3.696.0"
-      }
-    },
-    "node_modules/@aws-sdk/credential-provider-web-identity/node_modules/@smithy/property-provider": {
-      "version": "3.1.11",
-      "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.11.tgz",
-      "integrity": "sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/credential-providers": {
-      "version": "3.699.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.699.0.tgz",
-      "integrity": "sha512-jBjOntl9zN9Nvb0jmbMGRbiTzemDz64ij7W6BDavxBJRZpRoNeN0QCz6RolkCyXnyUJjo5mF2unY2wnv00A+LQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-sdk/client-cognito-identity": "3.699.0",
-        "@aws-sdk/client-sso": "3.696.0",
-        "@aws-sdk/client-sts": "3.699.0",
-        "@aws-sdk/core": "3.696.0",
-        "@aws-sdk/credential-provider-cognito-identity": "3.699.0",
-        "@aws-sdk/credential-provider-env": "3.696.0",
-        "@aws-sdk/credential-provider-http": "3.696.0",
-        "@aws-sdk/credential-provider-ini": "3.699.0",
-        "@aws-sdk/credential-provider-node": "3.699.0",
-        "@aws-sdk/credential-provider-process": "3.696.0",
-        "@aws-sdk/credential-provider-sso": "3.699.0",
-        "@aws-sdk/credential-provider-web-identity": "3.696.0",
-        "@aws-sdk/types": "3.696.0",
-        "@smithy/credential-provider-imds": "^3.2.6",
-        "@smithy/property-provider": "^3.1.9",
-        "@smithy/types": "^3.7.1",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/property-provider": {
-      "version": "3.1.11",
-      "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.11.tgz",
-      "integrity": "sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/middleware-host-header": {
-      "version": "3.696.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.696.0.tgz",
-      "integrity": "sha512-zELJp9Ta2zkX7ELggMN9qMCgekqZhFC5V2rOr4hJDEb/Tte7gpfKSObAnw/3AYiVqt36sjHKfdkoTsuwGdEoDg==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-sdk/types": "3.696.0",
-        "@smithy/protocol-http": "^4.1.7",
-        "@smithy/types": "^3.7.1",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/middleware-logger": {
-      "version": "3.696.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.696.0.tgz",
-      "integrity": "sha512-KhkHt+8AjCxcR/5Zp3++YPJPpFQzxpr+jmONiT/Jw2yqnSngZ0Yspm5wGoRx2hS1HJbyZNuaOWEGuJoxLeBKfA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-sdk/types": "3.696.0",
-        "@smithy/types": "^3.7.1",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/middleware-recursion-detection": {
-      "version": "3.696.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.696.0.tgz",
-      "integrity": "sha512-si/maV3Z0hH7qa99f9ru2xpS5HlfSVcasRlNUXKSDm611i7jFMWwGNLUOXFAOLhXotPX5G3Z6BLwL34oDeBMug==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-sdk/types": "3.696.0",
-        "@smithy/protocol-http": "^4.1.7",
-        "@smithy/types": "^3.7.1",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/middleware-user-agent": {
-      "version": "3.696.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.696.0.tgz",
-      "integrity": "sha512-Lvyj8CTyxrHI6GHd2YVZKIRI5Fmnugt3cpJo0VrKKEgK5zMySwEZ1n4dqPK6czYRWKd5+WnYHYAuU+Wdk6Jsjw==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-sdk/core": "3.696.0",
-        "@aws-sdk/types": "3.696.0",
-        "@aws-sdk/util-endpoints": "3.696.0",
-        "@smithy/core": "^2.5.3",
-        "@smithy/protocol-http": "^4.1.7",
-        "@smithy/types": "^3.7.1",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/region-config-resolver": {
-      "version": "3.696.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.696.0.tgz",
-      "integrity": "sha512-7EuH142lBXjI8yH6dVS/CZeiK/WZsmb/8zP6bQbVYpMrppSTgB3MzZZdxVZGzL5r8zPQOU10wLC4kIMy0qdBVQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-sdk/types": "3.696.0",
-        "@smithy/node-config-provider": "^3.1.11",
-        "@smithy/types": "^3.7.1",
-        "@smithy/util-config-provider": "^3.0.0",
-        "@smithy/util-middleware": "^3.0.10",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/token-providers": {
-      "version": "3.699.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.699.0.tgz",
-      "integrity": "sha512-kuiEW9DWs7fNos/SM+y58HCPhcIzm1nEZLhe2/7/6+TvAYLuEWURYsbK48gzsxXlaJ2k/jGY3nIsA7RptbMOwA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-sdk/types": "3.696.0",
-        "@smithy/property-provider": "^3.1.9",
-        "@smithy/shared-ini-file-loader": "^3.1.10",
-        "@smithy/types": "^3.7.1",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      },
-      "peerDependencies": {
-        "@aws-sdk/client-sso-oidc": "^3.699.0"
-      }
-    },
-    "node_modules/@aws-sdk/token-providers/node_modules/@smithy/property-provider": {
-      "version": "3.1.11",
-      "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.11.tgz",
-      "integrity": "sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/types": {
-      "version": "3.696.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.696.0.tgz",
-      "integrity": "sha512-9rTvUJIAj5d3//U5FDPWGJ1nFJLuWb30vugGOrWk7aNZ6y9tuA3PI7Cc9dP8WEXKVyK1vuuk8rSFP2iqXnlgrw==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.1",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/util-endpoints": {
-      "version": "3.696.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.696.0.tgz",
-      "integrity": "sha512-T5s0IlBVX+gkb9g/I6CLt4yAZVzMSiGnbUqWihWsHvQR1WOoIcndQy/Oz/IJXT9T2ipoy7a80gzV6a5mglrioA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-sdk/types": "3.696.0",
-        "@smithy/types": "^3.7.1",
-        "@smithy/util-endpoints": "^2.1.6",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/util-locate-window": {
-      "version": "3.693.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.693.0.tgz",
-      "integrity": "sha512-ttrag6haJLWABhLqtg1Uf+4LgHWIMOVSYL+VYZmAp2v4PUGOwWmWQH0Zk8RM7YuQcLfH/EoR72/Yxz6A4FKcuw==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@aws-sdk/util-user-agent-browser": {
-      "version": "3.696.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.696.0.tgz",
-      "integrity": "sha512-Z5rVNDdmPOe6ELoM5AhF/ja5tSjbe6ctSctDPb0JdDf4dT0v2MfwhJKzXju2RzX8Es/77Glh7MlaXLE0kCB9+Q==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-sdk/types": "3.696.0",
-        "@smithy/types": "^3.7.1",
-        "bowser": "^2.11.0",
-        "tslib": "^2.6.2"
-      }
-    },
-    "node_modules/@aws-sdk/util-user-agent-node": {
-      "version": "3.696.0",
-      "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.696.0.tgz",
-      "integrity": "sha512-KhKqcfyXIB0SCCt+qsu4eJjsfiOrNzK5dCV7RAW2YIpp+msxGUUX0NdRE9rkzjiv+3EMktgJm3eEIS+yxtlVdQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-sdk/middleware-user-agent": "3.696.0",
-        "@aws-sdk/types": "3.696.0",
-        "@smithy/node-config-provider": "^3.1.11",
-        "@smithy/types": "^3.7.1",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      },
-      "peerDependencies": {
-        "aws-crt": ">=1.0.0"
-      },
-      "peerDependenciesMeta": {
-        "aws-crt": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/@datadog/datadog-ci": {
-      "version": "2.45.1",
-      "resolved": "https://registry.npmjs.org/@datadog/datadog-ci/-/datadog-ci-2.45.1.tgz",
-      "integrity": "sha512-na4c4UuhT2jGFTOh+/uUVGR0CVj7c2B6Q7pRp9AMxb6NF2o3McjnSFJzmVc7YFdZwr+eHXeKXKf6bEYw/PjNWw==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-sdk/client-cloudwatch-logs": "^3.624.0",
-        "@aws-sdk/client-iam": "^3.624.0",
-        "@aws-sdk/client-lambda": "^3.624.0",
-        "@aws-sdk/client-sfn": "^3.624.0",
-        "@aws-sdk/core": "^3.624.0",
-        "@aws-sdk/credential-provider-ini": "^3.624.0",
-        "@aws-sdk/credential-providers": "^3.624.0",
-        "@google-cloud/logging": "^11.1.0",
-        "@google-cloud/run": "^1.4.0",
-        "@smithy/property-provider": "^2.0.12",
-        "@smithy/util-retry": "^2.0.4",
-        "@types/datadog-metrics": "0.6.1",
-        "ajv": "^8.12.0",
-        "ajv-formats": "^2.1.1",
-        "async-retry": "1.3.1",
-        "axios": "^1.7.4",
-        "chalk": "3.0.0",
-        "clipanion": "^3.2.1",
-        "datadog-metrics": "0.9.3",
-        "deep-extend": "0.6.0",
-        "deep-object-diff": "^1.1.9",
-        "fast-levenshtein": "^3.0.0",
-        "fast-xml-parser": "^4.4.1",
-        "form-data": "4.0.0",
-        "fuzzy": "^0.1.3",
-        "glob": "^7.1.4",
-        "google-auth-library": "^9.12.0",
-        "inquirer": "^8.2.5",
-        "inquirer-checkbox-plus-prompt": "^1.4.2",
-        "js-yaml": "3.13.1",
-        "jszip": "^3.10.1",
-        "ora": "5.4.1",
-        "proxy-agent": "^6.4.0",
-        "rimraf": "^3.0.2",
-        "semver": "^7.5.3",
-        "simple-git": "3.16.0",
-        "ssh2": "^1.15.0",
-        "ssh2-streams": "0.4.10",
-        "sshpk": "1.16.1",
-        "terminal-link": "2.1.1",
-        "tiny-async-pool": "^2.1.0",
-        "typanion": "^3.14.0",
-        "uuid": "^9.0.0",
-        "ws": "^7.5.10",
-        "xml2js": "0.5.0",
-        "yamux-js": "0.1.2"
-      },
-      "bin": {
-        "datadog-ci": "dist/cli.js"
-      },
-      "engines": {
-        "node": ">=14"
-      }
-    },
-    "node_modules/@google-cloud/common": {
-      "version": "5.0.2",
-      "resolved": "https://registry.npmjs.org/@google-cloud/common/-/common-5.0.2.tgz",
-      "integrity": "sha512-V7bmBKYQyu0eVG2BFejuUjlBt+zrya6vtsKdY+JxMM/dNntPF41vZ9+LhOshEUH01zOHEqBSvI7Dad7ZS6aUeA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@google-cloud/projectify": "^4.0.0",
-        "@google-cloud/promisify": "^4.0.0",
-        "arrify": "^2.0.1",
-        "duplexify": "^4.1.1",
-        "extend": "^3.0.2",
-        "google-auth-library": "^9.0.0",
-        "html-entities": "^2.5.2",
-        "retry-request": "^7.0.0",
-        "teeny-request": "^9.0.0"
-      },
-      "engines": {
-        "node": ">=14.0.0"
-      }
-    },
-    "node_modules/@google-cloud/logging": {
-      "version": "11.2.0",
-      "resolved": "https://registry.npmjs.org/@google-cloud/logging/-/logging-11.2.0.tgz",
-      "integrity": "sha512-Ma94jvuoMpbgNniwtelOt8w82hxK62FuOXZonEv0Hyk3B+/YVuLG/SWNyY9yMso/RXnPEc1fP2qo9kDrjf/b2w==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@google-cloud/common": "^5.0.0",
-        "@google-cloud/paginator": "^5.0.0",
-        "@google-cloud/projectify": "^4.0.0",
-        "@google-cloud/promisify": "^4.0.0",
-        "@opentelemetry/api": "^1.7.0",
-        "arrify": "^2.0.1",
-        "dot-prop": "^6.0.0",
-        "eventid": "^2.0.0",
-        "extend": "^3.0.2",
-        "gcp-metadata": "^6.0.0",
-        "google-auth-library": "^9.0.0",
-        "google-gax": "^4.0.3",
-        "on-finished": "^2.3.0",
-        "pumpify": "^2.0.1",
-        "stream-events": "^1.0.5",
-        "uuid": "^9.0.0"
-      },
-      "engines": {
-        "node": ">=14.0.0"
-      }
-    },
-    "node_modules/@google-cloud/paginator": {
-      "version": "5.0.2",
-      "resolved": "https://registry.npmjs.org/@google-cloud/paginator/-/paginator-5.0.2.tgz",
-      "integrity": "sha512-DJS3s0OVH4zFDB1PzjxAsHqJT6sKVbRwwML0ZBP9PbU7Yebtu/7SWMRzvO2J3nUi9pRNITCfu4LJeooM2w4pjg==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "arrify": "^2.0.0",
-        "extend": "^3.0.2"
-      },
-      "engines": {
-        "node": ">=14.0.0"
-      }
-    },
-    "node_modules/@google-cloud/projectify": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/@google-cloud/projectify/-/projectify-4.0.0.tgz",
-      "integrity": "sha512-MmaX6HeSvyPbWGwFq7mXdo0uQZLGBYCwziiLIGq5JVX+/bdI3SAq6bP98trV5eTWfLuvsMcIC1YJOF2vfteLFA==",
-      "license": "Apache-2.0",
-      "engines": {
-        "node": ">=14.0.0"
-      }
-    },
-    "node_modules/@google-cloud/promisify": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/@google-cloud/promisify/-/promisify-4.0.0.tgz",
-      "integrity": "sha512-Orxzlfb9c67A15cq2JQEyVc7wEsmFBmHjZWZYQMUyJ1qivXyMwdyNOs9odi79hze+2zqdTtu1E19IM/FtqZ10g==",
-      "license": "Apache-2.0",
-      "engines": {
-        "node": ">=14"
-      }
-    },
-    "node_modules/@google-cloud/run": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/@google-cloud/run/-/run-1.5.0.tgz",
-      "integrity": "sha512-Ct0ZIuicd2O6fJHv7Lbwl4CcCWKK7NjACvUc4pOJVbKo75B5proOa7/9TrXVpI6oWu1n7EFx1s8xsavYHLxRAg==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "google-gax": "^4.0.3"
-      },
-      "engines": {
-        "node": ">=14.0.0"
-      }
-    },
-    "node_modules/@grpc/grpc-js": {
-      "version": "1.12.4",
-      "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.12.4.tgz",
-      "integrity": "sha512-NBhrxEWnFh0FxeA0d//YP95lRFsSx2TNLEUQg4/W+5f/BMxcCjgOOIT24iD+ZB/tZw057j44DaIxja7w4XMrhg==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@grpc/proto-loader": "^0.7.13",
-        "@js-sdsl/ordered-map": "^4.4.2"
-      },
-      "engines": {
-        "node": ">=12.10.0"
-      }
-    },
-    "node_modules/@grpc/proto-loader": {
-      "version": "0.7.13",
-      "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz",
-      "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "lodash.camelcase": "^4.3.0",
-        "long": "^5.0.0",
-        "protobufjs": "^7.2.5",
-        "yargs": "^17.7.2"
-      },
-      "bin": {
-        "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/@js-sdsl/ordered-map": {
-      "version": "4.4.2",
-      "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz",
-      "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==",
-      "license": "MIT",
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/js-sdsl"
-      }
-    },
-    "node_modules/@kwsites/file-exists": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz",
-      "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==",
-      "license": "MIT",
-      "dependencies": {
-        "debug": "^4.1.1"
-      }
-    },
-    "node_modules/@kwsites/file-exists/node_modules/debug": {
-      "version": "4.4.0",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
-      "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
-      "license": "MIT",
-      "dependencies": {
-        "ms": "^2.1.3"
-      },
-      "engines": {
-        "node": ">=6.0"
-      },
-      "peerDependenciesMeta": {
-        "supports-color": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/@kwsites/file-exists/node_modules/ms": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
-      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
-      "license": "MIT"
-    },
-    "node_modules/@kwsites/promise-deferred": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz",
-      "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==",
-      "license": "MIT"
-    },
-    "node_modules/@opentelemetry/api": {
-      "version": "1.9.0",
-      "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz",
-      "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==",
-      "license": "Apache-2.0",
-      "engines": {
-        "node": ">=8.0.0"
-      }
-    },
-    "node_modules/@protobufjs/aspromise": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
-      "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==",
-      "license": "BSD-3-Clause"
-    },
-    "node_modules/@protobufjs/base64": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
-      "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==",
-      "license": "BSD-3-Clause"
-    },
-    "node_modules/@protobufjs/codegen": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz",
-      "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==",
-      "license": "BSD-3-Clause"
-    },
-    "node_modules/@protobufjs/eventemitter": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz",
-      "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==",
-      "license": "BSD-3-Clause"
-    },
-    "node_modules/@protobufjs/fetch": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz",
-      "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==",
-      "license": "BSD-3-Clause",
-      "dependencies": {
-        "@protobufjs/aspromise": "^1.1.1",
-        "@protobufjs/inquire": "^1.1.0"
-      }
-    },
-    "node_modules/@protobufjs/float": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
-      "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==",
-      "license": "BSD-3-Clause"
-    },
-    "node_modules/@protobufjs/inquire": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz",
-      "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==",
-      "license": "BSD-3-Clause"
-    },
-    "node_modules/@protobufjs/path": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
-      "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==",
-      "license": "BSD-3-Clause"
-    },
-    "node_modules/@protobufjs/pool": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
-      "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==",
-      "license": "BSD-3-Clause"
-    },
-    "node_modules/@protobufjs/utf8": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz",
-      "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==",
-      "license": "BSD-3-Clause"
-    },
-    "node_modules/@smithy/abort-controller": {
-      "version": "3.1.9",
-      "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.9.tgz",
-      "integrity": "sha512-yiW0WI30zj8ZKoSYNx90no7ugVn3khlyH/z5W8qtKBtVE6awRALbhSG+2SAHA1r6bO/6M9utxYKVZ3PCJ1rWxw==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/config-resolver": {
-      "version": "3.0.13",
-      "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.13.tgz",
-      "integrity": "sha512-Gr/qwzyPaTL1tZcq8WQyHhTZREER5R1Wytmz4WnVGL4onA3dNk6Btll55c8Vr58pLdvWZmtG8oZxJTw3t3q7Jg==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/node-config-provider": "^3.1.12",
-        "@smithy/types": "^3.7.2",
-        "@smithy/util-config-provider": "^3.0.0",
-        "@smithy/util-middleware": "^3.0.11",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/core": {
-      "version": "2.5.5",
-      "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.5.5.tgz",
-      "integrity": "sha512-G8G/sDDhXA7o0bOvkc7bgai6POuSld/+XhNnWAbpQTpLv2OZPvyqQ58tLPPlz0bSNsXktldDDREIv1LczFeNEw==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/middleware-serde": "^3.0.11",
-        "@smithy/protocol-http": "^4.1.8",
-        "@smithy/types": "^3.7.2",
-        "@smithy/util-body-length-browser": "^3.0.0",
-        "@smithy/util-middleware": "^3.0.11",
-        "@smithy/util-stream": "^3.3.2",
-        "@smithy/util-utf8": "^3.0.0",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/credential-provider-imds": {
-      "version": "3.2.8",
-      "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.8.tgz",
-      "integrity": "sha512-ZCY2yD0BY+K9iMXkkbnjo+08T2h8/34oHd0Jmh6BZUSZwaaGlGCyBT/3wnS7u7Xl33/EEfN4B6nQr3Gx5bYxgw==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/node-config-provider": "^3.1.12",
-        "@smithy/property-provider": "^3.1.11",
-        "@smithy/types": "^3.7.2",
-        "@smithy/url-parser": "^3.0.11",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/credential-provider-imds/node_modules/@smithy/property-provider": {
-      "version": "3.1.11",
-      "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.11.tgz",
-      "integrity": "sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/eventstream-codec": {
-      "version": "3.1.10",
-      "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-3.1.10.tgz",
-      "integrity": "sha512-323B8YckSbUH0nMIpXn7HZsAVKHYHFUODa8gG9cHo0ySvA1fr5iWaNT+iIL0UCqUzG6QPHA3BSsBtRQou4mMqQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@aws-crypto/crc32": "5.2.0",
-        "@smithy/types": "^3.7.2",
-        "@smithy/util-hex-encoding": "^3.0.0",
-        "tslib": "^2.6.2"
-      }
-    },
-    "node_modules/@smithy/eventstream-serde-browser": {
-      "version": "3.0.14",
-      "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.14.tgz",
-      "integrity": "sha512-kbrt0vjOIihW3V7Cqj1SXQvAI5BR8SnyQYsandva0AOR307cXAc+IhPngxIPslxTLfxwDpNu0HzCAq6g42kCPg==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/eventstream-serde-universal": "^3.0.13",
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/eventstream-serde-config-resolver": {
-      "version": "3.0.11",
-      "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.11.tgz",
-      "integrity": "sha512-P2pnEp4n75O+QHjyO7cbw/vsw5l93K/8EWyjNCAAybYwUmj3M+hjSQZ9P5TVdUgEG08ueMAP5R4FkuSkElZ5tQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/eventstream-serde-node": {
-      "version": "3.0.13",
-      "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.13.tgz",
-      "integrity": "sha512-zqy/9iwbj8Wysmvi7Lq7XFLeDgjRpTbCfwBhJa8WbrylTAHiAu6oQTwdY7iu2lxigbc9YYr9vPv5SzYny5tCXQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/eventstream-serde-universal": "^3.0.13",
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/eventstream-serde-universal": {
-      "version": "3.0.13",
-      "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.13.tgz",
-      "integrity": "sha512-L1Ib66+gg9uTnqp/18Gz4MDpJPKRE44geOjOQ2SVc0eiaO5l255ADziATZgjQjqumC7yPtp1XnjHlF1srcwjKw==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/eventstream-codec": "^3.1.10",
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/fetch-http-handler": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-4.1.2.tgz",
-      "integrity": "sha512-R7rU7Ae3ItU4rC0c5mB2sP5mJNbCfoDc8I5XlYjIZnquyUwec7fEo78F6DA3SmgJgkU1qTMcZJuGblxZsl10ZA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/protocol-http": "^4.1.8",
-        "@smithy/querystring-builder": "^3.0.11",
-        "@smithy/types": "^3.7.2",
-        "@smithy/util-base64": "^3.0.0",
-        "tslib": "^2.6.2"
-      }
-    },
-    "node_modules/@smithy/hash-node": {
-      "version": "3.0.11",
-      "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.11.tgz",
-      "integrity": "sha512-emP23rwYyZhQBvklqTtwetkQlqbNYirDiEEwXl2v0GYWMnCzxst7ZaRAnWuy28njp5kAH54lvkdG37MblZzaHA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "@smithy/util-buffer-from": "^3.0.0",
-        "@smithy/util-utf8": "^3.0.0",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/invalid-dependency": {
-      "version": "3.0.11",
-      "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.11.tgz",
-      "integrity": "sha512-NuQmVPEJjUX6c+UELyVz8kUx8Q539EDeNwbRyu4IIF8MeV7hUtq1FB3SHVyki2u++5XLMFqngeMKk7ccspnNyQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      }
-    },
-    "node_modules/@smithy/is-array-buffer": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz",
-      "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/middleware-content-length": {
-      "version": "3.0.13",
-      "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.13.tgz",
-      "integrity": "sha512-zfMhzojhFpIX3P5ug7jxTjfUcIPcGjcQYzB9t+rv0g1TX7B0QdwONW+ATouaLoD7h7LOw/ZlXfkq4xJ/g2TrIw==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/protocol-http": "^4.1.8",
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/middleware-endpoint": {
-      "version": "3.2.5",
-      "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.2.5.tgz",
-      "integrity": "sha512-VhJNs/s/lyx4weiZdXSloBgoLoS8osV0dKIain8nGmx7of3QFKu5BSdEuk1z/U8x9iwes1i+XCiNusEvuK1ijg==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/core": "^2.5.5",
-        "@smithy/middleware-serde": "^3.0.11",
-        "@smithy/node-config-provider": "^3.1.12",
-        "@smithy/shared-ini-file-loader": "^3.1.12",
-        "@smithy/types": "^3.7.2",
-        "@smithy/url-parser": "^3.0.11",
-        "@smithy/util-middleware": "^3.0.11",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/middleware-retry": {
-      "version": "3.0.29",
-      "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.29.tgz",
-      "integrity": "sha512-/FfI/N2tIVCG9escHYLLABJlNHbO1gWFSdMlvbPOTV+Y+Aa8Q1FuS7Yaghb8NUfFmGYjkbeIu3bnbta6KbarsA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/node-config-provider": "^3.1.12",
-        "@smithy/protocol-http": "^4.1.8",
-        "@smithy/service-error-classification": "^3.0.11",
-        "@smithy/smithy-client": "^3.4.6",
-        "@smithy/types": "^3.7.2",
-        "@smithy/util-middleware": "^3.0.11",
-        "@smithy/util-retry": "^3.0.11",
-        "tslib": "^2.6.2",
-        "uuid": "^9.0.1"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/middleware-retry/node_modules/@smithy/util-retry": {
-      "version": "3.0.11",
-      "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.11.tgz",
-      "integrity": "sha512-hJUC6W7A3DQgaee3Hp9ZFcOxVDZzmBIRBPlUAk8/fSOEl7pE/aX7Dci0JycNOnm9Mfr0KV2XjIlUOcGWXQUdVQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/service-error-classification": "^3.0.11",
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/middleware-serde": {
-      "version": "3.0.11",
-      "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.11.tgz",
-      "integrity": "sha512-KzPAeySp/fOoQA82TpnwItvX8BBURecpx6ZMu75EZDkAcnPtO6vf7q4aH5QHs/F1s3/snQaSFbbUMcFFZ086Mw==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/middleware-stack": {
-      "version": "3.0.11",
-      "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.11.tgz",
-      "integrity": "sha512-1HGo9a6/ikgOMrTrWL/WiN9N8GSVYpuRQO5kjstAq4CvV59bjqnh7TbdXGQ4vxLD3xlSjfBjq5t1SOELePsLnA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/node-config-provider": {
-      "version": "3.1.12",
-      "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.12.tgz",
-      "integrity": "sha512-O9LVEu5J/u/FuNlZs+L7Ikn3lz7VB9hb0GtPT9MQeiBmtK8RSY3ULmsZgXhe6VAlgTw0YO+paQx4p8xdbs43vQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/property-provider": "^3.1.11",
-        "@smithy/shared-ini-file-loader": "^3.1.12",
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/node-config-provider/node_modules/@smithy/property-provider": {
-      "version": "3.1.11",
-      "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.11.tgz",
-      "integrity": "sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/node-http-handler": {
-      "version": "3.3.2",
-      "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.3.2.tgz",
-      "integrity": "sha512-t4ng1DAd527vlxvOfKFYEe6/QFBcsj7WpNlWTyjorwXXcKw3XlltBGbyHfSJ24QT84nF+agDha9tNYpzmSRZPA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/abort-controller": "^3.1.9",
-        "@smithy/protocol-http": "^4.1.8",
-        "@smithy/querystring-builder": "^3.0.11",
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/property-provider": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-2.2.0.tgz",
-      "integrity": "sha512-+xiil2lFhtTRzXkx8F053AV46QnIw6e7MV8od5Mi68E1ICOjCeCHw2XfLnDEUHnT9WGUIkwcqavXjfwuJbGlpg==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^2.12.0",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=14.0.0"
-      }
-    },
-    "node_modules/@smithy/property-provider/node_modules/@smithy/types": {
-      "version": "2.12.0",
-      "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.12.0.tgz",
-      "integrity": "sha512-QwYgloJ0sVNBeBuBs65cIkTbfzV/Q6ZNPCJ99EICFEdJYG50nGIY/uYXp+TbsdJReIuPr0a0kXmCvren3MbRRw==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=14.0.0"
-      }
-    },
-    "node_modules/@smithy/protocol-http": {
-      "version": "4.1.8",
-      "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.8.tgz",
-      "integrity": "sha512-hmgIAVyxw1LySOwkgMIUN0kjN8TG9Nc85LJeEmEE/cNEe2rkHDUWhnJf2gxcSRFLWsyqWsrZGw40ROjUogg+Iw==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/querystring-builder": {
-      "version": "3.0.11",
-      "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.11.tgz",
-      "integrity": "sha512-u+5HV/9uJaeLj5XTb6+IEF/dokWWkEqJ0XiaRRogyREmKGUgZnNecLucADLdauWFKUNbQfulHFEZEdjwEBjXRg==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "@smithy/util-uri-escape": "^3.0.0",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/querystring-parser": {
-      "version": "3.0.11",
-      "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.11.tgz",
-      "integrity": "sha512-Je3kFvCsFMnso1ilPwA7GtlbPaTixa3WwC+K21kmMZHsBEOZYQaqxcMqeFFoU7/slFjKDIpiiPydvdJm8Q/MCw==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/service-error-classification": {
-      "version": "3.0.11",
-      "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.11.tgz",
-      "integrity": "sha512-QnYDPkyewrJzCyaeI2Rmp7pDwbUETe+hU8ADkXmgNusO1bgHBH7ovXJiYmba8t0fNfJx75fE8dlM6SEmZxheog==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/shared-ini-file-loader": {
-      "version": "3.1.12",
-      "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.12.tgz",
-      "integrity": "sha512-1xKSGI+U9KKdbG2qDvIR9dGrw3CNx+baqJfyr0igKEpjbHL5stsqAesYBzHChYHlelWtb87VnLWlhvfCz13H8Q==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/signature-v4": {
-      "version": "4.2.4",
-      "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.2.4.tgz",
-      "integrity": "sha512-5JWeMQYg81TgU4cG+OexAWdvDTs5JDdbEZx+Qr1iPbvo91QFGzjy0IkXAKaXUHqmKUJgSHK0ZxnCkgZpzkeNTA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/is-array-buffer": "^3.0.0",
-        "@smithy/protocol-http": "^4.1.8",
-        "@smithy/types": "^3.7.2",
-        "@smithy/util-hex-encoding": "^3.0.0",
-        "@smithy/util-middleware": "^3.0.11",
-        "@smithy/util-uri-escape": "^3.0.0",
-        "@smithy/util-utf8": "^3.0.0",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/smithy-client": {
-      "version": "3.4.6",
-      "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.4.6.tgz",
-      "integrity": "sha512-j/WYdfzdx4asqb0YZch1rb6Y5OQcuTdXY7xnEMtc05diB5jfLQQtys9J/2lzmGKri9m9mUBrcnNTv3jbXvtk7A==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/core": "^2.5.5",
-        "@smithy/middleware-endpoint": "^3.2.5",
-        "@smithy/middleware-stack": "^3.0.11",
-        "@smithy/protocol-http": "^4.1.8",
-        "@smithy/types": "^3.7.2",
-        "@smithy/util-stream": "^3.3.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/types": {
-      "version": "3.7.2",
-      "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.7.2.tgz",
-      "integrity": "sha512-bNwBYYmN8Eh9RyjS1p2gW6MIhSO2rl7X9QeLM8iTdcGRP+eDiIWDt66c9IysCc22gefKszZv+ubV9qZc7hdESg==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/url-parser": {
-      "version": "3.0.11",
-      "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.11.tgz",
-      "integrity": "sha512-TmlqXkSk8ZPhfc+SQutjmFr5FjC0av3GZP4B/10caK1SbRwe/v+Wzu/R6xEKxoNqL+8nY18s1byiy6HqPG37Aw==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/querystring-parser": "^3.0.11",
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      }
-    },
-    "node_modules/@smithy/util-base64": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz",
-      "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/util-buffer-from": "^3.0.0",
-        "@smithy/util-utf8": "^3.0.0",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/util-body-length-browser": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz",
-      "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "tslib": "^2.6.2"
-      }
-    },
-    "node_modules/@smithy/util-body-length-node": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz",
-      "integrity": "sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/util-buffer-from": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz",
-      "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/is-array-buffer": "^3.0.0",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/util-config-provider": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz",
-      "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/util-defaults-mode-browser": {
-      "version": "3.0.29",
-      "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.29.tgz",
-      "integrity": "sha512-7k0kOfDjnSM44GG74UnjEixtHmtF/do6pCNEvp1DQlFjktEz8pv06p9RSjxp2J3Lv6I3+Ba9FLfurpFeBv+Pvw==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/property-provider": "^3.1.11",
-        "@smithy/smithy-client": "^3.4.6",
-        "@smithy/types": "^3.7.2",
-        "bowser": "^2.11.0",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">= 10.0.0"
-      }
-    },
-    "node_modules/@smithy/util-defaults-mode-browser/node_modules/@smithy/property-provider": {
-      "version": "3.1.11",
-      "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.11.tgz",
-      "integrity": "sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/util-defaults-mode-node": {
-      "version": "3.0.29",
-      "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.29.tgz",
-      "integrity": "sha512-lu8jaXAt1TIVkTAKMuGdZwWQ1L03iV/n8WPbY5hdjcNqLg2ysp5DqiINmtuLL8EgzDv1TXvKDaBAN+9bGH4sEQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/config-resolver": "^3.0.13",
-        "@smithy/credential-provider-imds": "^3.2.8",
-        "@smithy/node-config-provider": "^3.1.12",
-        "@smithy/property-provider": "^3.1.11",
-        "@smithy/smithy-client": "^3.4.6",
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">= 10.0.0"
-      }
-    },
-    "node_modules/@smithy/util-defaults-mode-node/node_modules/@smithy/property-provider": {
-      "version": "3.1.11",
-      "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.11.tgz",
-      "integrity": "sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/util-endpoints": {
-      "version": "2.1.7",
-      "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.1.7.tgz",
-      "integrity": "sha512-tSfcqKcN/Oo2STEYCABVuKgJ76nyyr6skGl9t15hs+YaiU06sgMkN7QYjo0BbVw+KT26zok3IzbdSOksQ4YzVw==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/node-config-provider": "^3.1.12",
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/util-hex-encoding": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz",
-      "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/util-middleware": {
-      "version": "3.0.11",
-      "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.11.tgz",
-      "integrity": "sha512-dWpyc1e1R6VoXrwLoLDd57U1z6CwNSdkM69Ie4+6uYh2GC7Vg51Qtan7ITzczuVpqezdDTKJGJB95fFvvjU/ow==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/util-retry": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-2.2.0.tgz",
-      "integrity": "sha512-q9+pAFPTfftHXRytmZ7GzLFFrEGavqapFc06XxzZFcSIGERXMerXxCitjOG1prVDR9QdjqotF40SWvbqcCpf8g==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/service-error-classification": "^2.1.5",
-        "@smithy/types": "^2.12.0",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">= 14.0.0"
-      }
-    },
-    "node_modules/@smithy/util-retry/node_modules/@smithy/service-error-classification": {
-      "version": "2.1.5",
-      "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-2.1.5.tgz",
-      "integrity": "sha512-uBDTIBBEdAQryvHdc5W8sS5YX7RQzF683XrHePVdFmAgKiMofU15FLSM0/HU03hKTnazdNRFa0YHS7+ArwoUSQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/types": "^2.12.0"
-      },
-      "engines": {
-        "node": ">=14.0.0"
-      }
-    },
-    "node_modules/@smithy/util-retry/node_modules/@smithy/types": {
-      "version": "2.12.0",
-      "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.12.0.tgz",
-      "integrity": "sha512-QwYgloJ0sVNBeBuBs65cIkTbfzV/Q6ZNPCJ99EICFEdJYG50nGIY/uYXp+TbsdJReIuPr0a0kXmCvren3MbRRw==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=14.0.0"
-      }
-    },
-    "node_modules/@smithy/util-stream": {
-      "version": "3.3.2",
-      "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.3.2.tgz",
-      "integrity": "sha512-sInAqdiVeisUGYAv/FrXpmJ0b4WTFmciTRqzhb7wVuem9BHvhIG7tpiYHLDWrl2stOokNZpTTGqz3mzB2qFwXg==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/fetch-http-handler": "^4.1.2",
-        "@smithy/node-http-handler": "^3.3.2",
-        "@smithy/types": "^3.7.2",
-        "@smithy/util-base64": "^3.0.0",
-        "@smithy/util-buffer-from": "^3.0.0",
-        "@smithy/util-hex-encoding": "^3.0.0",
-        "@smithy/util-utf8": "^3.0.0",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/util-uri-escape": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz",
-      "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/util-utf8": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz",
-      "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/util-buffer-from": "^3.0.0",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@smithy/util-waiter": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-3.2.0.tgz",
-      "integrity": "sha512-PpjSboaDUE6yl+1qlg3Si57++e84oXdWGbuFUSAciXsVfEZJJJupR2Nb0QuXHiunt2vGR+1PTizOMvnUPaG2Qg==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@smithy/abort-controller": "^3.1.9",
-        "@smithy/types": "^3.7.2",
-        "tslib": "^2.6.2"
-      },
-      "engines": {
-        "node": ">=16.0.0"
-      }
-    },
-    "node_modules/@tootallnate/once": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
-      "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 10"
-      }
-    },
-    "node_modules/@tootallnate/quickjs-emscripten": {
-      "version": "0.23.0",
-      "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz",
-      "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==",
-      "license": "MIT"
-    },
-    "node_modules/@types/caseless": {
-      "version": "0.12.5",
-      "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.5.tgz",
-      "integrity": "sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==",
-      "license": "MIT"
-    },
-    "node_modules/@types/datadog-metrics": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/@types/datadog-metrics/-/datadog-metrics-0.6.1.tgz",
-      "integrity": "sha512-p6zVpfmNcXwtcXjgpz7do/fKyfndGhU5sGJVtb5Gn5PvLDiQUAgD0mI/itf/99sBi9DRxeyhFQ9dQF6OxxQNbA==",
-      "license": "MIT"
-    },
-    "node_modules/@types/long": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz",
-      "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==",
-      "license": "MIT"
-    },
-    "node_modules/@types/node": {
-      "version": "22.10.1",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.1.tgz",
-      "integrity": "sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==",
-      "license": "MIT",
-      "dependencies": {
-        "undici-types": "~6.20.0"
-      }
-    },
-    "node_modules/@types/request": {
-      "version": "2.48.12",
-      "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.12.tgz",
-      "integrity": "sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw==",
-      "license": "MIT",
-      "dependencies": {
-        "@types/caseless": "*",
-        "@types/node": "*",
-        "@types/tough-cookie": "*",
-        "form-data": "^2.5.0"
-      }
-    },
-    "node_modules/@types/request/node_modules/form-data": {
-      "version": "2.5.2",
-      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.2.tgz",
-      "integrity": "sha512-GgwY0PS7DbXqajuGf4OYlsrIu3zgxD6Vvql43IBhm6MahqA5SK/7mwhtNj2AdH2z35YR34ujJ7BN+3fFC3jP5Q==",
-      "license": "MIT",
-      "dependencies": {
-        "asynckit": "^0.4.0",
-        "combined-stream": "^1.0.6",
-        "mime-types": "^2.1.12",
-        "safe-buffer": "^5.2.1"
-      },
-      "engines": {
-        "node": ">= 0.12"
-      }
-    },
-    "node_modules/@types/tough-cookie": {
-      "version": "4.0.5",
-      "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz",
-      "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==",
-      "license": "MIT"
-    },
-    "node_modules/@types/uuid": {
-      "version": "9.0.8",
-      "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz",
-      "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==",
-      "license": "MIT"
-    },
-    "node_modules/abort-controller": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
-      "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
-      "license": "MIT",
-      "dependencies": {
-        "event-target-shim": "^5.0.0"
-      },
-      "engines": {
-        "node": ">=6.5"
-      }
-    },
-    "node_modules/agent-base": {
-      "version": "7.1.3",
-      "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz",
-      "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 14"
-      }
-    },
-    "node_modules/ajv": {
-      "version": "8.17.1",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
-      "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
-      "license": "MIT",
-      "dependencies": {
-        "fast-deep-equal": "^3.1.3",
-        "fast-uri": "^3.0.1",
-        "json-schema-traverse": "^1.0.0",
-        "require-from-string": "^2.0.2"
-      },
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/epoberezkin"
-      }
-    },
-    "node_modules/ajv-formats": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
-      "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
-      "license": "MIT",
-      "dependencies": {
-        "ajv": "^8.0.0"
-      },
-      "peerDependencies": {
-        "ajv": "^8.0.0"
-      },
-      "peerDependenciesMeta": {
-        "ajv": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/ansi-escapes": {
-      "version": "4.3.2",
-      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
-      "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
-      "license": "MIT",
-      "dependencies": {
-        "type-fest": "^0.21.3"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/ansi-regex": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "license": "MIT",
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/argparse": {
-      "version": "1.0.10",
-      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
-      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
-      "license": "MIT",
-      "dependencies": {
-        "sprintf-js": "~1.0.2"
-      }
-    },
-    "node_modules/arrify": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz",
-      "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/asn1": {
-      "version": "0.2.6",
-      "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
-      "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
-      "license": "MIT",
-      "dependencies": {
-        "safer-buffer": "~2.1.0"
-      }
-    },
-    "node_modules/assert-plus": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
-      "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.8"
-      }
-    },
-    "node_modules/ast-types": {
-      "version": "0.13.4",
-      "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz",
-      "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==",
-      "license": "MIT",
-      "dependencies": {
-        "tslib": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/async-retry": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.1.tgz",
-      "integrity": "sha512-aiieFW/7h3hY0Bq5d+ktDBejxuwR78vRu9hDUdR8rNhSaQ29VzPL4AoIRG7D/c7tdenwOcKvgPM6tIxB3cB6HA==",
-      "license": "MIT",
-      "dependencies": {
-        "retry": "0.12.0"
-      }
-    },
-    "node_modules/asynckit": {
-      "version": "0.4.0",
-      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
-      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
-      "license": "MIT"
-    },
-    "node_modules/axios": {
-      "version": "1.7.9",
-      "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz",
-      "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==",
-      "license": "MIT",
-      "dependencies": {
-        "follow-redirects": "^1.15.6",
-        "form-data": "^4.0.0",
-        "proxy-from-env": "^1.1.0"
-      }
-    },
-    "node_modules/balanced-match": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
-      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
-      "license": "MIT"
-    },
-    "node_modules/base64-js": {
-      "version": "1.5.1",
-      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
-      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ],
-      "license": "MIT"
-    },
-    "node_modules/basic-ftp": {
-      "version": "5.0.5",
-      "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz",
-      "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=10.0.0"
-      }
-    },
-    "node_modules/bcrypt-pbkdf": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
-      "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
-      "license": "BSD-3-Clause",
-      "dependencies": {
-        "tweetnacl": "^0.14.3"
-      }
-    },
-    "node_modules/bignumber.js": {
-      "version": "9.1.2",
-      "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz",
-      "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==",
-      "license": "MIT",
-      "engines": {
-        "node": "*"
-      }
-    },
-    "node_modules/bl": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
-      "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
-      "license": "MIT",
-      "dependencies": {
-        "buffer": "^5.5.0",
-        "inherits": "^2.0.4",
-        "readable-stream": "^3.4.0"
-      }
-    },
-    "node_modules/bowser": {
-      "version": "2.11.0",
-      "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz",
-      "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==",
-      "license": "MIT"
-    },
-    "node_modules/brace-expansion": {
-      "version": "1.1.11",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
-      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
-      "license": "MIT",
-      "dependencies": {
-        "balanced-match": "^1.0.0",
-        "concat-map": "0.0.1"
-      }
-    },
-    "node_modules/buffer": {
-      "version": "5.7.1",
-      "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
-      "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ],
-      "license": "MIT",
-      "dependencies": {
-        "base64-js": "^1.3.1",
-        "ieee754": "^1.1.13"
-      }
-    },
-    "node_modules/buffer-equal-constant-time": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
-      "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
-      "license": "BSD-3-Clause"
-    },
-    "node_modules/buildcheck": {
-      "version": "0.0.6",
-      "resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.6.tgz",
-      "integrity": "sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A==",
-      "optional": true,
-      "engines": {
-        "node": ">=10.0.0"
-      }
-    },
-    "node_modules/chalk": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
-      "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/chardet": {
-      "version": "0.7.0",
-      "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
-      "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
-      "license": "MIT"
-    },
-    "node_modules/cli-cursor": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
-      "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
-      "license": "MIT",
-      "dependencies": {
-        "restore-cursor": "^3.1.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/cli-spinners": {
-      "version": "2.9.2",
-      "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz",
-      "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/cli-width": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
-      "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
-      "license": "ISC",
-      "engines": {
-        "node": ">= 10"
-      }
-    },
-    "node_modules/clipanion": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmjs.org/clipanion/-/clipanion-3.2.1.tgz",
-      "integrity": "sha512-dYFdjLb7y1ajfxQopN05mylEpK9ZX0sO1/RfMXdfmwjlIsPkbh4p7A682x++zFPLDCo1x3p82dtljHf5cW2LKA==",
-      "license": "MIT",
-      "workspaces": [
-        "website"
-      ],
-      "dependencies": {
-        "typanion": "^3.8.0"
-      },
-      "peerDependencies": {
-        "typanion": "*"
-      }
-    },
-    "node_modules/cliui": {
-      "version": "8.0.1",
-      "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
-      "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
-      "license": "ISC",
-      "dependencies": {
-        "string-width": "^4.2.0",
-        "strip-ansi": "^6.0.1",
-        "wrap-ansi": "^7.0.0"
-      },
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/cliui/node_modules/wrap-ansi": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
-      "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.0.0",
-        "string-width": "^4.1.0",
-        "strip-ansi": "^6.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
-      }
-    },
-    "node_modules/clone": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
-      "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.8"
-      }
-    },
-    "node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "license": "MIT",
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "license": "MIT"
-    },
-    "node_modules/combined-stream": {
-      "version": "1.0.8",
-      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
-      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
-      "license": "MIT",
-      "dependencies": {
-        "delayed-stream": "~1.0.0"
-      },
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/concat-map": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
-      "license": "MIT"
-    },
-    "node_modules/core-util-is": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
-      "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
-      "license": "MIT"
-    },
-    "node_modules/cpu-features": {
-      "version": "0.0.10",
-      "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.10.tgz",
-      "integrity": "sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==",
-      "hasInstallScript": true,
-      "optional": true,
-      "dependencies": {
-        "buildcheck": "~0.0.6",
-        "nan": "^2.19.0"
-      },
-      "engines": {
-        "node": ">=10.0.0"
-      }
-    },
-    "node_modules/dashdash": {
-      "version": "1.14.1",
-      "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
-      "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
-      "license": "MIT",
-      "dependencies": {
-        "assert-plus": "^1.0.0"
-      },
-      "engines": {
-        "node": ">=0.10"
-      }
-    },
-    "node_modules/data-uri-to-buffer": {
-      "version": "6.0.2",
-      "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz",
-      "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 14"
-      }
-    },
-    "node_modules/datadog-metrics": {
-      "version": "0.9.3",
-      "resolved": "https://registry.npmjs.org/datadog-metrics/-/datadog-metrics-0.9.3.tgz",
-      "integrity": "sha512-BVsBX2t+4yA3tHs7DnB5H01cHVNiGJ/bHA8y6JppJDyXG7s2DLm6JaozPGpgsgVGd42Is1CHRG/yMDQpt877Xg==",
-      "license": "MIT",
-      "dependencies": {
-        "debug": "3.1.0",
-        "dogapi": "2.8.4"
-      }
-    },
-    "node_modules/debug": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-      "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-      "license": "MIT",
-      "dependencies": {
-        "ms": "2.0.0"
-      }
-    },
-    "node_modules/deep-extend": {
-      "version": "0.6.0",
-      "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
-      "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=4.0.0"
-      }
-    },
-    "node_modules/deep-object-diff": {
-      "version": "1.1.9",
-      "resolved": "https://registry.npmjs.org/deep-object-diff/-/deep-object-diff-1.1.9.tgz",
-      "integrity": "sha512-Rn+RuwkmkDwCi2/oXOFS9Gsr5lJZu/yTGpK7wAaAIE75CC+LCGEZHpY6VQJa/RoJcrmaA/docWJZvYohlNkWPA==",
-      "license": "MIT"
-    },
-    "node_modules/defaults": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
-      "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
-      "license": "MIT",
-      "dependencies": {
-        "clone": "^1.0.2"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/degenerator": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz",
-      "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==",
-      "license": "MIT",
-      "dependencies": {
-        "ast-types": "^0.13.4",
-        "escodegen": "^2.1.0",
-        "esprima": "^4.0.1"
-      },
-      "engines": {
-        "node": ">= 14"
-      }
-    },
-    "node_modules/delayed-stream": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
-      "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.4.0"
-      }
-    },
-    "node_modules/dogapi": {
-      "version": "2.8.4",
-      "resolved": "https://registry.npmjs.org/dogapi/-/dogapi-2.8.4.tgz",
-      "integrity": "sha512-065fsvu5dB0o4+ENtLjZILvXMClDNH/yA9H6L8nsdcNiz9l0Hzpn7aQaCOPYXxqyzq4CRPOdwkFXUjDOXfRGbg==",
-      "license": "MIT",
-      "dependencies": {
-        "extend": "^3.0.2",
-        "json-bigint": "^1.0.0",
-        "lodash": "^4.17.21",
-        "minimist": "^1.2.5",
-        "rc": "^1.2.8"
-      },
-      "bin": {
-        "dogapi": "bin/dogapi"
-      }
-    },
-    "node_modules/dot-prop": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz",
-      "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==",
-      "license": "MIT",
-      "dependencies": {
-        "is-obj": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/duplexify": {
-      "version": "4.1.3",
-      "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz",
-      "integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==",
-      "license": "MIT",
-      "dependencies": {
-        "end-of-stream": "^1.4.1",
-        "inherits": "^2.0.3",
-        "readable-stream": "^3.1.1",
-        "stream-shift": "^1.0.2"
-      }
-    },
-    "node_modules/ecc-jsbn": {
-      "version": "0.1.2",
-      "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
-      "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
-      "license": "MIT",
-      "dependencies": {
-        "jsbn": "~0.1.0",
-        "safer-buffer": "^2.1.0"
-      }
-    },
-    "node_modules/ecc-jsbn/node_modules/jsbn": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
-      "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==",
-      "license": "MIT"
-    },
-    "node_modules/ecdsa-sig-formatter": {
-      "version": "1.0.11",
-      "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
-      "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "safe-buffer": "^5.0.1"
-      }
-    },
-    "node_modules/ee-first": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
-      "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
-      "license": "MIT"
-    },
-    "node_modules/emoji-regex": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
-      "license": "MIT"
-    },
-    "node_modules/end-of-stream": {
-      "version": "1.4.4",
-      "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
-      "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
-      "license": "MIT",
-      "dependencies": {
-        "once": "^1.4.0"
-      }
-    },
-    "node_modules/escalade": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
-      "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/escape-string-regexp": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.8.0"
-      }
-    },
-    "node_modules/escodegen": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
-      "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==",
-      "license": "BSD-2-Clause",
-      "dependencies": {
-        "esprima": "^4.0.1",
-        "estraverse": "^5.2.0",
-        "esutils": "^2.0.2"
-      },
-      "bin": {
-        "escodegen": "bin/escodegen.js",
-        "esgenerate": "bin/esgenerate.js"
-      },
-      "engines": {
-        "node": ">=6.0"
-      },
-      "optionalDependencies": {
-        "source-map": "~0.6.1"
-      }
-    },
-    "node_modules/esprima": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
-      "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
-      "license": "BSD-2-Clause",
-      "bin": {
-        "esparse": "bin/esparse.js",
-        "esvalidate": "bin/esvalidate.js"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/estraverse": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
-      "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
-      "license": "BSD-2-Clause",
-      "engines": {
-        "node": ">=4.0"
-      }
-    },
-    "node_modules/esutils": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
-      "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
-      "license": "BSD-2-Clause",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/event-target-shim": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
-      "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/eventid": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/eventid/-/eventid-2.0.1.tgz",
-      "integrity": "sha512-sPNTqiMokAvV048P2c9+foqVJzk49o6d4e0D/sq5jog3pw+4kBgyR0gaM1FM7Mx6Kzd9dztesh9oYz1LWWOpzw==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "uuid": "^8.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/eventid/node_modules/uuid": {
-      "version": "8.3.2",
-      "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
-      "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
-      "license": "MIT",
-      "bin": {
-        "uuid": "dist/bin/uuid"
-      }
-    },
-    "node_modules/extend": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
-      "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
-      "license": "MIT"
-    },
-    "node_modules/external-editor": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
-      "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
-      "license": "MIT",
-      "dependencies": {
-        "chardet": "^0.7.0",
-        "iconv-lite": "^0.4.24",
-        "tmp": "^0.0.33"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/fast-deep-equal": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
-      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
-      "license": "MIT"
-    },
-    "node_modules/fast-levenshtein": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-3.0.0.tgz",
-      "integrity": "sha512-hKKNajm46uNmTlhHSyZkmToAc56uZJwYq7yrciZjqOxnlfQwERDQJmHPUp7m1m9wx8vgOe8IaCKZ5Kv2k1DdCQ==",
-      "license": "MIT",
-      "dependencies": {
-        "fastest-levenshtein": "^1.0.7"
-      }
-    },
-    "node_modules/fast-uri": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz",
-      "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==",
-      "license": "BSD-3-Clause"
-    },
-    "node_modules/fast-xml-parser": {
-      "version": "4.5.0",
-      "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.0.tgz",
-      "integrity": "sha512-/PlTQCI96+fZMAOLMZK4CWG1ItCbfZ/0jx7UIJFChPNrx7tcEgerUgWbeieCM9MfHInUDyK8DWYZ+YrywDJuTg==",
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/NaturalIntelligence"
-        },
-        {
-          "type": "paypal",
-          "url": "https://paypal.me/naturalintelligence"
-        }
-      ],
-      "license": "MIT",
-      "dependencies": {
-        "strnum": "^1.0.5"
-      },
-      "bin": {
-        "fxparser": "src/cli/cli.js"
-      }
-    },
-    "node_modules/fastest-levenshtein": {
-      "version": "1.0.16",
-      "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
-      "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 4.9.1"
-      }
-    },
-    "node_modules/figures": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
-      "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
-      "license": "MIT",
-      "dependencies": {
-        "escape-string-regexp": "^1.0.5"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/follow-redirects": {
-      "version": "1.15.9",
-      "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
-      "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
-      "funding": [
-        {
-          "type": "individual",
-          "url": "https://github.com/sponsors/RubenVerborgh"
-        }
-      ],
-      "license": "MIT",
-      "engines": {
-        "node": ">=4.0"
-      },
-      "peerDependenciesMeta": {
-        "debug": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/form-data": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
-      "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
-      "license": "MIT",
-      "dependencies": {
-        "asynckit": "^0.4.0",
-        "combined-stream": "^1.0.8",
-        "mime-types": "^2.1.12"
-      },
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/fs.realpath": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
-      "license": "ISC"
-    },
-    "node_modules/fuzzy": {
-      "version": "0.1.3",
-      "resolved": "https://registry.npmjs.org/fuzzy/-/fuzzy-0.1.3.tgz",
-      "integrity": "sha512-/gZffu4ykarLrCiP3Ygsa86UAo1E5vEVlvTrpkKywXSbP9Xhln3oSp9QSV57gEq3JFFpGJ4GZ+5zdEp3FcUh4w==",
-      "engines": {
-        "node": ">= 0.6.0"
-      }
-    },
-    "node_modules/gaxios": {
-      "version": "6.7.1",
-      "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-6.7.1.tgz",
-      "integrity": "sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "extend": "^3.0.2",
-        "https-proxy-agent": "^7.0.1",
-        "is-stream": "^2.0.0",
-        "node-fetch": "^2.6.9",
-        "uuid": "^9.0.1"
-      },
-      "engines": {
-        "node": ">=14"
-      }
-    },
-    "node_modules/gcp-metadata": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/gcp-metadata/-/gcp-metadata-6.1.0.tgz",
-      "integrity": "sha512-Jh/AIwwgaxan+7ZUUmRLCjtchyDiqh4KjBJ5tW3plBZb5iL/BPcso8A5DlzeD9qlw0duCamnNdpFjxwaT0KyKg==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "gaxios": "^6.0.0",
-        "json-bigint": "^1.0.0"
-      },
-      "engines": {
-        "node": ">=14"
-      }
-    },
-    "node_modules/get-caller-file": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
-      "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
-      "license": "ISC",
-      "engines": {
-        "node": "6.* || 8.* || >= 10.*"
-      }
-    },
-    "node_modules/get-uri": {
-      "version": "6.0.4",
-      "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.4.tgz",
-      "integrity": "sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==",
-      "license": "MIT",
-      "dependencies": {
-        "basic-ftp": "^5.0.2",
-        "data-uri-to-buffer": "^6.0.2",
-        "debug": "^4.3.4"
-      },
-      "engines": {
-        "node": ">= 14"
-      }
-    },
-    "node_modules/get-uri/node_modules/debug": {
-      "version": "4.4.0",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
-      "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
-      "license": "MIT",
-      "dependencies": {
-        "ms": "^2.1.3"
-      },
-      "engines": {
-        "node": ">=6.0"
-      },
-      "peerDependenciesMeta": {
-        "supports-color": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/get-uri/node_modules/ms": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
-      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
-      "license": "MIT"
-    },
-    "node_modules/getpass": {
-      "version": "0.1.7",
-      "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
-      "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
-      "license": "MIT",
-      "dependencies": {
-        "assert-plus": "^1.0.0"
-      }
-    },
-    "node_modules/glob": {
-      "version": "7.2.3",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
-      "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
-      "deprecated": "Glob versions prior to v9 are no longer supported",
-      "license": "ISC",
-      "dependencies": {
-        "fs.realpath": "^1.0.0",
-        "inflight": "^1.0.4",
-        "inherits": "2",
-        "minimatch": "^3.1.1",
-        "once": "^1.3.0",
-        "path-is-absolute": "^1.0.0"
-      },
-      "engines": {
-        "node": "*"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/google-auth-library": {
-      "version": "9.15.0",
-      "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-9.15.0.tgz",
-      "integrity": "sha512-7ccSEJFDFO7exFbO6NRyC+xH8/mZ1GZGG2xxx9iHxZWcjUjJpjWxIMw3cofAKcueZ6DATiukmmprD7yavQHOyQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "base64-js": "^1.3.0",
-        "ecdsa-sig-formatter": "^1.0.11",
-        "gaxios": "^6.1.1",
-        "gcp-metadata": "^6.1.0",
-        "gtoken": "^7.0.0",
-        "jws": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=14"
-      }
-    },
-    "node_modules/google-gax": {
-      "version": "4.4.1",
-      "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-4.4.1.tgz",
-      "integrity": "sha512-Phyp9fMfA00J3sZbJxbbB4jC55b7DBjE3F6poyL3wKMEBVKA79q6BGuHcTiM28yOzVql0NDbRL8MLLh8Iwk9Dg==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "@grpc/grpc-js": "^1.10.9",
-        "@grpc/proto-loader": "^0.7.13",
-        "@types/long": "^4.0.0",
-        "abort-controller": "^3.0.0",
-        "duplexify": "^4.0.0",
-        "google-auth-library": "^9.3.0",
-        "node-fetch": "^2.7.0",
-        "object-hash": "^3.0.0",
-        "proto3-json-serializer": "^2.0.2",
-        "protobufjs": "^7.3.2",
-        "retry-request": "^7.0.0",
-        "uuid": "^9.0.1"
-      },
-      "engines": {
-        "node": ">=14"
-      }
-    },
-    "node_modules/gtoken": {
-      "version": "7.1.0",
-      "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-7.1.0.tgz",
-      "integrity": "sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw==",
-      "license": "MIT",
-      "dependencies": {
-        "gaxios": "^6.0.0",
-        "jws": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=14.0.0"
-      }
-    },
-    "node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/html-entities": {
-      "version": "2.5.2",
-      "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz",
-      "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==",
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/mdevils"
-        },
-        {
-          "type": "patreon",
-          "url": "https://patreon.com/mdevils"
-        }
-      ],
-      "license": "MIT"
-    },
-    "node_modules/http-proxy-agent": {
-      "version": "7.0.2",
-      "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
-      "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
-      "license": "MIT",
-      "dependencies": {
-        "agent-base": "^7.1.0",
-        "debug": "^4.3.4"
-      },
-      "engines": {
-        "node": ">= 14"
-      }
-    },
-    "node_modules/http-proxy-agent/node_modules/debug": {
-      "version": "4.4.0",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
-      "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
-      "license": "MIT",
-      "dependencies": {
-        "ms": "^2.1.3"
-      },
-      "engines": {
-        "node": ">=6.0"
-      },
-      "peerDependenciesMeta": {
-        "supports-color": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/http-proxy-agent/node_modules/ms": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
-      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
-      "license": "MIT"
-    },
-    "node_modules/https-proxy-agent": {
-      "version": "7.0.6",
-      "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
-      "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
-      "license": "MIT",
-      "dependencies": {
-        "agent-base": "^7.1.2",
-        "debug": "4"
-      },
-      "engines": {
-        "node": ">= 14"
-      }
-    },
-    "node_modules/https-proxy-agent/node_modules/debug": {
-      "version": "4.4.0",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
-      "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
-      "license": "MIT",
-      "dependencies": {
-        "ms": "^2.1.3"
-      },
-      "engines": {
-        "node": ">=6.0"
-      },
-      "peerDependenciesMeta": {
-        "supports-color": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/https-proxy-agent/node_modules/ms": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
-      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
-      "license": "MIT"
-    },
-    "node_modules/iconv-lite": {
-      "version": "0.4.24",
-      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
-      "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
-      "license": "MIT",
-      "dependencies": {
-        "safer-buffer": ">= 2.1.2 < 3"
-      },
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/ieee754": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
-      "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ],
-      "license": "BSD-3-Clause"
-    },
-    "node_modules/immediate": {
-      "version": "3.0.6",
-      "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
-      "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
-      "license": "MIT"
-    },
-    "node_modules/inflight": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
-      "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
-      "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
-      "license": "ISC",
-      "dependencies": {
-        "once": "^1.3.0",
-        "wrappy": "1"
-      }
-    },
-    "node_modules/inherits": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
-      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
-      "license": "ISC"
-    },
-    "node_modules/ini": {
-      "version": "1.3.8",
-      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
-      "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
-      "license": "ISC"
-    },
-    "node_modules/inquirer": {
-      "version": "8.2.6",
-      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz",
-      "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-escapes": "^4.2.1",
-        "chalk": "^4.1.1",
-        "cli-cursor": "^3.1.0",
-        "cli-width": "^3.0.0",
-        "external-editor": "^3.0.3",
-        "figures": "^3.0.0",
-        "lodash": "^4.17.21",
-        "mute-stream": "0.0.8",
-        "ora": "^5.4.1",
-        "run-async": "^2.4.0",
-        "rxjs": "^7.5.5",
-        "string-width": "^4.1.0",
-        "strip-ansi": "^6.0.0",
-        "through": "^2.3.6",
-        "wrap-ansi": "^6.0.1"
-      },
-      "engines": {
-        "node": ">=12.0.0"
-      }
-    },
-    "node_modules/inquirer-checkbox-plus-prompt": {
-      "version": "1.4.2",
-      "resolved": "https://registry.npmjs.org/inquirer-checkbox-plus-prompt/-/inquirer-checkbox-plus-prompt-1.4.2.tgz",
-      "integrity": "sha512-W8/NL9x5A81Oq9ZfbYW5c1LuwtAhc/oB/u9YZZejna0pqrajj27XhnUHygJV0Vn5TvcDy1VJcD2Ld9kTk40dvg==",
-      "license": "MIT",
-      "dependencies": {
-        "chalk": "4.1.2",
-        "cli-cursor": "^3.1.0",
-        "figures": "^3.0.0",
-        "lodash": "^4.17.5",
-        "rxjs": "^6.6.7"
-      },
-      "peerDependencies": {
-        "inquirer": "< 9.x"
-      }
-    },
-    "node_modules/inquirer-checkbox-plus-prompt/node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/inquirer-checkbox-plus-prompt/node_modules/rxjs": {
-      "version": "6.6.7",
-      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
-      "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "tslib": "^1.9.0"
-      },
-      "engines": {
-        "npm": ">=2.0.0"
-      }
-    },
-    "node_modules/inquirer-checkbox-plus-prompt/node_modules/tslib": {
-      "version": "1.14.1",
-      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
-      "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
-      "license": "0BSD"
-    },
-    "node_modules/inquirer/node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/ip-address": {
-      "version": "9.0.5",
-      "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
-      "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
-      "license": "MIT",
-      "dependencies": {
-        "jsbn": "1.1.0",
-        "sprintf-js": "^1.1.3"
-      },
-      "engines": {
-        "node": ">= 12"
-      }
-    },
-    "node_modules/ip-address/node_modules/sprintf-js": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
-      "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
-      "license": "BSD-3-Clause"
-    },
-    "node_modules/is-fullwidth-code-point": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/is-interactive": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
-      "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/is-obj": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
-      "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/is-stream": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
-      "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/is-unicode-supported": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
-      "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/isarray": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
-      "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
-      "license": "MIT"
-    },
-    "node_modules/js-yaml": {
-      "version": "3.13.1",
-      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
-      "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
-      "license": "MIT",
-      "dependencies": {
-        "argparse": "^1.0.7",
-        "esprima": "^4.0.0"
-      },
-      "bin": {
-        "js-yaml": "bin/js-yaml.js"
-      }
-    },
-    "node_modules/jsbn": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
-      "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==",
-      "license": "MIT"
-    },
-    "node_modules/json-bigint": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
-      "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
-      "license": "MIT",
-      "dependencies": {
-        "bignumber.js": "^9.0.0"
-      }
-    },
-    "node_modules/json-schema-traverse": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
-      "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
-      "license": "MIT"
-    },
-    "node_modules/jszip": {
-      "version": "3.10.1",
-      "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
-      "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
-      "license": "(MIT OR GPL-3.0-or-later)",
-      "dependencies": {
-        "lie": "~3.3.0",
-        "pako": "~1.0.2",
-        "readable-stream": "~2.3.6",
-        "setimmediate": "^1.0.5"
-      }
-    },
-    "node_modules/jszip/node_modules/readable-stream": {
-      "version": "2.3.8",
-      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
-      "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
-      "license": "MIT",
-      "dependencies": {
-        "core-util-is": "~1.0.0",
-        "inherits": "~2.0.3",
-        "isarray": "~1.0.0",
-        "process-nextick-args": "~2.0.0",
-        "safe-buffer": "~5.1.1",
-        "string_decoder": "~1.1.1",
-        "util-deprecate": "~1.0.1"
-      }
-    },
-    "node_modules/jszip/node_modules/safe-buffer": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
-      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
-      "license": "MIT"
-    },
-    "node_modules/jszip/node_modules/string_decoder": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
-      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
-      "license": "MIT",
-      "dependencies": {
-        "safe-buffer": "~5.1.0"
-      }
-    },
-    "node_modules/jwa": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz",
-      "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==",
-      "license": "MIT",
-      "dependencies": {
-        "buffer-equal-constant-time": "1.0.1",
-        "ecdsa-sig-formatter": "1.0.11",
-        "safe-buffer": "^5.0.1"
-      }
-    },
-    "node_modules/jws": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz",
-      "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==",
-      "license": "MIT",
-      "dependencies": {
-        "jwa": "^2.0.0",
-        "safe-buffer": "^5.0.1"
-      }
-    },
-    "node_modules/lie": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
-      "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
-      "license": "MIT",
-      "dependencies": {
-        "immediate": "~3.0.5"
-      }
-    },
-    "node_modules/lodash": {
-      "version": "4.17.21",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
-      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
-      "license": "MIT"
-    },
-    "node_modules/lodash.camelcase": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
-      "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
-      "license": "MIT"
-    },
-    "node_modules/log-symbols": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
-      "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
-      "license": "MIT",
-      "dependencies": {
-        "chalk": "^4.1.0",
-        "is-unicode-supported": "^0.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/log-symbols/node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/long": {
-      "version": "5.2.3",
-      "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz",
-      "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==",
-      "license": "Apache-2.0"
-    },
-    "node_modules/lru-cache": {
-      "version": "7.18.3",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz",
-      "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==",
-      "license": "ISC",
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/mime-db": {
-      "version": "1.52.0",
-      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
-      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/mime-types": {
-      "version": "2.1.35",
-      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
-      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
-      "license": "MIT",
-      "dependencies": {
-        "mime-db": "1.52.0"
-      },
-      "engines": {
-        "node": ">= 0.6"
-      }
-    },
-    "node_modules/mimic-fn": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
-      "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/minimatch": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
-      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
-      "license": "ISC",
-      "dependencies": {
-        "brace-expansion": "^1.1.7"
-      },
-      "engines": {
-        "node": "*"
-      }
-    },
-    "node_modules/minimist": {
-      "version": "1.2.8",
-      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
-      "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
-      "license": "MIT",
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/ms": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
-      "license": "MIT"
-    },
-    "node_modules/mute-stream": {
-      "version": "0.0.8",
-      "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
-      "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
-      "license": "ISC"
-    },
-    "node_modules/nan": {
-      "version": "2.22.0",
-      "resolved": "https://registry.npmjs.org/nan/-/nan-2.22.0.tgz",
-      "integrity": "sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==",
-      "license": "MIT",
-      "optional": true
-    },
-    "node_modules/netmask": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz",
-      "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 0.4.0"
-      }
-    },
-    "node_modules/node-fetch": {
-      "version": "2.7.0",
-      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
-      "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
-      "license": "MIT",
-      "dependencies": {
-        "whatwg-url": "^5.0.0"
-      },
-      "engines": {
-        "node": "4.x || >=6.0.0"
-      },
-      "peerDependencies": {
-        "encoding": "^0.1.0"
-      },
-      "peerDependenciesMeta": {
-        "encoding": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/object-hash": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
-      "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/on-finished": {
-      "version": "2.4.1",
-      "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
-      "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
-      "license": "MIT",
-      "dependencies": {
-        "ee-first": "1.1.1"
-      },
-      "engines": {
-        "node": ">= 0.8"
-      }
-    },
-    "node_modules/once": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
-      "license": "ISC",
-      "dependencies": {
-        "wrappy": "1"
-      }
-    },
-    "node_modules/onetime": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
-      "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
-      "license": "MIT",
-      "dependencies": {
-        "mimic-fn": "^2.1.0"
-      },
-      "engines": {
-        "node": ">=6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/ora": {
-      "version": "5.4.1",
-      "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
-      "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==",
-      "license": "MIT",
-      "dependencies": {
-        "bl": "^4.1.0",
-        "chalk": "^4.1.0",
-        "cli-cursor": "^3.1.0",
-        "cli-spinners": "^2.5.0",
-        "is-interactive": "^1.0.0",
-        "is-unicode-supported": "^0.1.0",
-        "log-symbols": "^4.1.0",
-        "strip-ansi": "^6.0.0",
-        "wcwidth": "^1.0.1"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/ora/node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/os-tmpdir": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
-      "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/pac-proxy-agent": {
-      "version": "7.1.0",
-      "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.1.0.tgz",
-      "integrity": "sha512-Z5FnLVVZSnX7WjBg0mhDtydeRZ1xMcATZThjySQUHqr+0ksP8kqaw23fNKkaaN/Z8gwLUs/W7xdl0I75eP2Xyw==",
-      "license": "MIT",
-      "dependencies": {
-        "@tootallnate/quickjs-emscripten": "^0.23.0",
-        "agent-base": "^7.1.2",
-        "debug": "^4.3.4",
-        "get-uri": "^6.0.1",
-        "http-proxy-agent": "^7.0.0",
-        "https-proxy-agent": "^7.0.6",
-        "pac-resolver": "^7.0.1",
-        "socks-proxy-agent": "^8.0.5"
-      },
-      "engines": {
-        "node": ">= 14"
-      }
-    },
-    "node_modules/pac-proxy-agent/node_modules/debug": {
-      "version": "4.4.0",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
-      "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
-      "license": "MIT",
-      "dependencies": {
-        "ms": "^2.1.3"
-      },
-      "engines": {
-        "node": ">=6.0"
-      },
-      "peerDependenciesMeta": {
-        "supports-color": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/pac-proxy-agent/node_modules/ms": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
-      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
-      "license": "MIT"
-    },
-    "node_modules/pac-resolver": {
-      "version": "7.0.1",
-      "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz",
-      "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==",
-      "license": "MIT",
-      "dependencies": {
-        "degenerator": "^5.0.0",
-        "netmask": "^2.0.2"
-      },
-      "engines": {
-        "node": ">= 14"
-      }
-    },
-    "node_modules/pako": {
-      "version": "1.0.11",
-      "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
-      "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
-      "license": "(MIT AND Zlib)"
-    },
-    "node_modules/path-is-absolute": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-      "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/process-nextick-args": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
-      "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
-      "license": "MIT"
-    },
-    "node_modules/proto3-json-serializer": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/proto3-json-serializer/-/proto3-json-serializer-2.0.2.tgz",
-      "integrity": "sha512-SAzp/O4Yh02jGdRc+uIrGoe87dkN/XtwxfZ4ZyafJHymd79ozp5VG5nyZ7ygqPM5+cpLDjjGnYFUkngonyDPOQ==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "protobufjs": "^7.2.5"
-      },
-      "engines": {
-        "node": ">=14.0.0"
-      }
-    },
-    "node_modules/protobufjs": {
-      "version": "7.4.0",
-      "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz",
-      "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==",
-      "hasInstallScript": true,
-      "license": "BSD-3-Clause",
-      "dependencies": {
-        "@protobufjs/aspromise": "^1.1.2",
-        "@protobufjs/base64": "^1.1.2",
-        "@protobufjs/codegen": "^2.0.4",
-        "@protobufjs/eventemitter": "^1.1.0",
-        "@protobufjs/fetch": "^1.1.0",
-        "@protobufjs/float": "^1.0.2",
-        "@protobufjs/inquire": "^1.1.0",
-        "@protobufjs/path": "^1.1.2",
-        "@protobufjs/pool": "^1.1.0",
-        "@protobufjs/utf8": "^1.1.0",
-        "@types/node": ">=13.7.0",
-        "long": "^5.0.0"
-      },
-      "engines": {
-        "node": ">=12.0.0"
-      }
-    },
-    "node_modules/proxy-agent": {
-      "version": "6.5.0",
-      "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz",
-      "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==",
-      "license": "MIT",
-      "dependencies": {
-        "agent-base": "^7.1.2",
-        "debug": "^4.3.4",
-        "http-proxy-agent": "^7.0.1",
-        "https-proxy-agent": "^7.0.6",
-        "lru-cache": "^7.14.1",
-        "pac-proxy-agent": "^7.1.0",
-        "proxy-from-env": "^1.1.0",
-        "socks-proxy-agent": "^8.0.5"
-      },
-      "engines": {
-        "node": ">= 14"
-      }
-    },
-    "node_modules/proxy-agent/node_modules/debug": {
-      "version": "4.4.0",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
-      "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
-      "license": "MIT",
-      "dependencies": {
-        "ms": "^2.1.3"
-      },
-      "engines": {
-        "node": ">=6.0"
-      },
-      "peerDependenciesMeta": {
-        "supports-color": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/proxy-agent/node_modules/ms": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
-      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
-      "license": "MIT"
-    },
-    "node_modules/proxy-from-env": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
-      "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
-      "license": "MIT"
-    },
-    "node_modules/pump": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz",
-      "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==",
-      "license": "MIT",
-      "dependencies": {
-        "end-of-stream": "^1.1.0",
-        "once": "^1.3.1"
-      }
-    },
-    "node_modules/pumpify": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-2.0.1.tgz",
-      "integrity": "sha512-m7KOje7jZxrmutanlkS1daj1dS6z6BgslzOXmcSEpIlCxM3VJH7lG5QLeck/6hgF6F4crFf01UtQmNsJfweTAw==",
-      "license": "MIT",
-      "dependencies": {
-        "duplexify": "^4.1.1",
-        "inherits": "^2.0.3",
-        "pump": "^3.0.0"
-      }
-    },
-    "node_modules/rc": {
-      "version": "1.2.8",
-      "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
-      "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
-      "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
-      "dependencies": {
-        "deep-extend": "^0.6.0",
-        "ini": "~1.3.0",
-        "minimist": "^1.2.0",
-        "strip-json-comments": "~2.0.1"
-      },
-      "bin": {
-        "rc": "cli.js"
-      }
-    },
-    "node_modules/readable-stream": {
-      "version": "3.6.2",
-      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
-      "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
-      "license": "MIT",
-      "dependencies": {
-        "inherits": "^2.0.3",
-        "string_decoder": "^1.1.1",
-        "util-deprecate": "^1.0.1"
-      },
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/require-directory": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
-      "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/require-from-string": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
-      "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/restore-cursor": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
-      "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
-      "license": "MIT",
-      "dependencies": {
-        "onetime": "^5.1.0",
-        "signal-exit": "^3.0.2"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/retry": {
-      "version": "0.12.0",
-      "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
-      "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 4"
-      }
-    },
-    "node_modules/retry-request": {
-      "version": "7.0.2",
-      "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-7.0.2.tgz",
-      "integrity": "sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w==",
-      "license": "MIT",
-      "dependencies": {
-        "@types/request": "^2.48.8",
-        "extend": "^3.0.2",
-        "teeny-request": "^9.0.0"
-      },
-      "engines": {
-        "node": ">=14"
-      }
-    },
-    "node_modules/rimraf": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
-      "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
-      "deprecated": "Rimraf versions prior to v4 are no longer supported",
-      "license": "ISC",
-      "dependencies": {
-        "glob": "^7.1.3"
-      },
-      "bin": {
-        "rimraf": "bin.js"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/run-async": {
-      "version": "2.4.1",
-      "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
-      "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.12.0"
-      }
-    },
-    "node_modules/rxjs": {
-      "version": "7.8.1",
-      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
-      "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "tslib": "^2.1.0"
-      }
-    },
-    "node_modules/safe-buffer": {
-      "version": "5.2.1",
-      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
-      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ],
-      "license": "MIT"
-    },
-    "node_modules/safer-buffer": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
-      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
-      "license": "MIT"
-    },
-    "node_modules/sax": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
-      "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
-      "license": "ISC"
-    },
-    "node_modules/semver": {
-      "version": "7.6.3",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
-      "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
-      "license": "ISC",
-      "bin": {
-        "semver": "bin/semver.js"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/setimmediate": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
-      "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
-      "license": "MIT"
-    },
-    "node_modules/signal-exit": {
-      "version": "3.0.7",
-      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
-      "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
-      "license": "ISC"
-    },
-    "node_modules/simple-git": {
-      "version": "3.16.0",
-      "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.16.0.tgz",
-      "integrity": "sha512-zuWYsOLEhbJRWVxpjdiXl6eyAyGo/KzVW+KFhhw9MqEEJttcq+32jTWSGyxTdf9e/YCohxRE+9xpWFj9FdiJNw==",
-      "license": "MIT",
-      "dependencies": {
-        "@kwsites/file-exists": "^1.1.1",
-        "@kwsites/promise-deferred": "^1.1.1",
-        "debug": "^4.3.4"
-      },
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/steveukx/git-js?sponsor=1"
-      }
-    },
-    "node_modules/simple-git/node_modules/debug": {
-      "version": "4.4.0",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
-      "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
-      "license": "MIT",
-      "dependencies": {
-        "ms": "^2.1.3"
-      },
-      "engines": {
-        "node": ">=6.0"
-      },
-      "peerDependenciesMeta": {
-        "supports-color": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/simple-git/node_modules/ms": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
-      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
-      "license": "MIT"
-    },
-    "node_modules/smart-buffer": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
-      "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
-      "license": "MIT",
-      "engines": {
-        "node": ">= 6.0.0",
-        "npm": ">= 3.0.0"
-      }
-    },
-    "node_modules/socks": {
-      "version": "2.8.3",
-      "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
-      "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==",
-      "license": "MIT",
-      "dependencies": {
-        "ip-address": "^9.0.5",
-        "smart-buffer": "^4.2.0"
-      },
-      "engines": {
-        "node": ">= 10.0.0",
-        "npm": ">= 3.0.0"
-      }
-    },
-    "node_modules/socks-proxy-agent": {
-      "version": "8.0.5",
-      "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz",
-      "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==",
-      "license": "MIT",
-      "dependencies": {
-        "agent-base": "^7.1.2",
-        "debug": "^4.3.4",
-        "socks": "^2.8.3"
-      },
-      "engines": {
-        "node": ">= 14"
-      }
-    },
-    "node_modules/socks-proxy-agent/node_modules/debug": {
-      "version": "4.4.0",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
-      "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
-      "license": "MIT",
-      "dependencies": {
-        "ms": "^2.1.3"
-      },
-      "engines": {
-        "node": ">=6.0"
-      },
-      "peerDependenciesMeta": {
-        "supports-color": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/socks-proxy-agent/node_modules/ms": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
-      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
-      "license": "MIT"
-    },
-    "node_modules/source-map": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-      "license": "BSD-3-Clause",
-      "optional": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/sprintf-js": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
-      "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
-      "license": "BSD-3-Clause"
-    },
-    "node_modules/ssh2": {
-      "version": "1.16.0",
-      "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.16.0.tgz",
-      "integrity": "sha512-r1X4KsBGedJqo7h8F5c4Ybpcr5RjyP+aWIG007uBPRjmdQWfEiVLzSK71Zji1B9sKxwaCvD8y8cwSkYrlLiRRg==",
-      "hasInstallScript": true,
-      "dependencies": {
-        "asn1": "^0.2.6",
-        "bcrypt-pbkdf": "^1.0.2"
-      },
-      "engines": {
-        "node": ">=10.16.0"
-      },
-      "optionalDependencies": {
-        "cpu-features": "~0.0.10",
-        "nan": "^2.20.0"
-      }
-    },
-    "node_modules/ssh2-streams": {
-      "version": "0.4.10",
-      "resolved": "https://registry.npmjs.org/ssh2-streams/-/ssh2-streams-0.4.10.tgz",
-      "integrity": "sha512-8pnlMjvnIZJvmTzUIIA5nT4jr2ZWNNVHwyXfMGdRJbug9TpI3kd99ffglgfSWqujVv/0gxwMsDn9j9RVst8yhQ==",
-      "dependencies": {
-        "asn1": "~0.2.0",
-        "bcrypt-pbkdf": "^1.0.2",
-        "streamsearch": "~0.1.2"
-      },
-      "engines": {
-        "node": ">=5.2.0"
-      }
-    },
-    "node_modules/sshpk": {
-      "version": "1.16.1",
-      "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
-      "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
-      "license": "MIT",
-      "dependencies": {
-        "asn1": "~0.2.3",
-        "assert-plus": "^1.0.0",
-        "bcrypt-pbkdf": "^1.0.0",
-        "dashdash": "^1.12.0",
-        "ecc-jsbn": "~0.1.1",
-        "getpass": "^0.1.1",
-        "jsbn": "~0.1.0",
-        "safer-buffer": "^2.0.2",
-        "tweetnacl": "~0.14.0"
-      },
-      "bin": {
-        "sshpk-conv": "bin/sshpk-conv",
-        "sshpk-sign": "bin/sshpk-sign",
-        "sshpk-verify": "bin/sshpk-verify"
-      },
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/sshpk/node_modules/jsbn": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
-      "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==",
-      "license": "MIT"
-    },
-    "node_modules/stream-events": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz",
-      "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==",
-      "license": "MIT",
-      "dependencies": {
-        "stubs": "^3.0.0"
-      }
-    },
-    "node_modules/stream-shift": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz",
-      "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==",
-      "license": "MIT"
-    },
-    "node_modules/streamsearch": {
-      "version": "0.1.2",
-      "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz",
-      "integrity": "sha512-jos8u++JKm0ARcSUTAZXOVC0mSox7Bhn6sBgty73P1f3JGf7yG2clTbBNHUdde/kdvP2FESam+vM6l8jBrNxHA==",
-      "engines": {
-        "node": ">=0.8.0"
-      }
-    },
-    "node_modules/string_decoder": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
-      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
-      "license": "MIT",
-      "dependencies": {
-        "safe-buffer": "~5.2.0"
-      }
-    },
-    "node_modules/string-width": {
-      "version": "4.2.3",
-      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
-      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
-      "license": "MIT",
-      "dependencies": {
-        "emoji-regex": "^8.0.0",
-        "is-fullwidth-code-point": "^3.0.0",
-        "strip-ansi": "^6.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/strip-ansi": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-regex": "^5.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/strip-json-comments": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
-      "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/strnum": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
-      "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==",
-      "license": "MIT"
-    },
-    "node_modules/stubs": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz",
-      "integrity": "sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw==",
-      "license": "MIT"
-    },
-    "node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "license": "MIT",
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/supports-hyperlinks": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz",
-      "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==",
-      "license": "MIT",
-      "dependencies": {
-        "has-flag": "^4.0.0",
-        "supports-color": "^7.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/teeny-request": {
-      "version": "9.0.0",
-      "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-9.0.0.tgz",
-      "integrity": "sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==",
-      "license": "Apache-2.0",
-      "dependencies": {
-        "http-proxy-agent": "^5.0.0",
-        "https-proxy-agent": "^5.0.0",
-        "node-fetch": "^2.6.9",
-        "stream-events": "^1.0.5",
-        "uuid": "^9.0.0"
-      },
-      "engines": {
-        "node": ">=14"
-      }
-    },
-    "node_modules/teeny-request/node_modules/agent-base": {
-      "version": "6.0.2",
-      "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
-      "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
-      "license": "MIT",
-      "dependencies": {
-        "debug": "4"
-      },
-      "engines": {
-        "node": ">= 6.0.0"
-      }
-    },
-    "node_modules/teeny-request/node_modules/debug": {
-      "version": "4.4.0",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
-      "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
-      "license": "MIT",
-      "dependencies": {
-        "ms": "^2.1.3"
-      },
-      "engines": {
-        "node": ">=6.0"
-      },
-      "peerDependenciesMeta": {
-        "supports-color": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/teeny-request/node_modules/http-proxy-agent": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
-      "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==",
-      "license": "MIT",
-      "dependencies": {
-        "@tootallnate/once": "2",
-        "agent-base": "6",
-        "debug": "4"
-      },
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/teeny-request/node_modules/https-proxy-agent": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
-      "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
-      "license": "MIT",
-      "dependencies": {
-        "agent-base": "6",
-        "debug": "4"
-      },
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/teeny-request/node_modules/ms": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
-      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
-      "license": "MIT"
-    },
-    "node_modules/terminal-link": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz",
-      "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-escapes": "^4.2.1",
-        "supports-hyperlinks": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/through": {
-      "version": "2.3.8",
-      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
-      "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
-      "license": "MIT"
-    },
-    "node_modules/tiny-async-pool": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/tiny-async-pool/-/tiny-async-pool-2.1.0.tgz",
-      "integrity": "sha512-ltAHPh/9k0STRQqaoUX52NH4ZQYAJz24ZAEwf1Zm+HYg3l9OXTWeqWKyYsHu40wF/F0rxd2N2bk5sLvX2qlSvg==",
-      "license": "MIT"
-    },
-    "node_modules/tmp": {
-      "version": "0.0.33",
-      "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
-      "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
-      "license": "MIT",
-      "dependencies": {
-        "os-tmpdir": "~1.0.2"
-      },
-      "engines": {
-        "node": ">=0.6.0"
-      }
-    },
-    "node_modules/tr46": {
-      "version": "0.0.3",
-      "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
-      "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
-      "license": "MIT"
-    },
-    "node_modules/tslib": {
-      "version": "2.8.1",
-      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
-      "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
-      "license": "0BSD"
-    },
-    "node_modules/tweetnacl": {
-      "version": "0.14.5",
-      "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
-      "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==",
-      "license": "Unlicense"
-    },
-    "node_modules/typanion": {
-      "version": "3.14.0",
-      "resolved": "https://registry.npmjs.org/typanion/-/typanion-3.14.0.tgz",
-      "integrity": "sha512-ZW/lVMRabETuYCd9O9ZvMhAh8GslSqaUjxmK/JLPCh6l73CvLBiuXswj/+7LdnWOgYsQ130FqLzFz5aGT4I3Ug==",
-      "license": "MIT",
-      "workspaces": [
-        "website"
-      ]
-    },
-    "node_modules/type-fest": {
-      "version": "0.21.3",
-      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
-      "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
-      "license": "(MIT OR CC0-1.0)",
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/undici-types": {
-      "version": "6.20.0",
-      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
-      "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
-      "license": "MIT"
-    },
-    "node_modules/util-deprecate": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
-      "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
-      "license": "MIT"
-    },
-    "node_modules/uuid": {
-      "version": "9.0.1",
-      "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
-      "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
-      "funding": [
-        "https://github.com/sponsors/broofa",
-        "https://github.com/sponsors/ctavan"
-      ],
-      "license": "MIT",
-      "bin": {
-        "uuid": "dist/bin/uuid"
-      }
-    },
-    "node_modules/wcwidth": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
-      "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
-      "license": "MIT",
-      "dependencies": {
-        "defaults": "^1.0.3"
-      }
-    },
-    "node_modules/webidl-conversions": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
-      "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
-      "license": "BSD-2-Clause"
-    },
-    "node_modules/whatwg-url": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
-      "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
-      "license": "MIT",
-      "dependencies": {
-        "tr46": "~0.0.3",
-        "webidl-conversions": "^3.0.0"
-      }
-    },
-    "node_modules/wrap-ansi": {
-      "version": "6.2.0",
-      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
-      "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
-      "license": "MIT",
-      "dependencies": {
-        "ansi-styles": "^4.0.0",
-        "string-width": "^4.1.0",
-        "strip-ansi": "^6.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/wrappy": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
-      "license": "ISC"
-    },
-    "node_modules/ws": {
-      "version": "7.5.10",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
-      "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=8.3.0"
-      },
-      "peerDependencies": {
-        "bufferutil": "^4.0.1",
-        "utf-8-validate": "^5.0.2"
-      },
-      "peerDependenciesMeta": {
-        "bufferutil": {
-          "optional": true
-        },
-        "utf-8-validate": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/xml2js": {
-      "version": "0.5.0",
-      "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz",
-      "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==",
-      "license": "MIT",
-      "dependencies": {
-        "sax": ">=0.6.0",
-        "xmlbuilder": "~11.0.0"
-      },
-      "engines": {
-        "node": ">=4.0.0"
-      }
-    },
-    "node_modules/xmlbuilder": {
-      "version": "11.0.1",
-      "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
-      "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
-      "license": "MIT",
-      "engines": {
-        "node": ">=4.0"
-      }
-    },
-    "node_modules/y18n": {
-      "version": "5.0.8",
-      "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
-      "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
-      "license": "ISC",
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/yamux-js": {
-      "version": "0.1.2",
-      "resolved": "https://registry.npmjs.org/yamux-js/-/yamux-js-0.1.2.tgz",
-      "integrity": "sha512-bhsPlPZ9xB4Dawyf6nkS58u4F3IvGCaybkEKGnneUeepcI7MPoG3Tt6SaKCU5x/kP2/2w20Qm/GqbpwAM16vYw==",
-      "license": "MIT"
-    },
-    "node_modules/yargs": {
-      "version": "17.7.2",
-      "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
-      "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
-      "license": "MIT",
-      "dependencies": {
-        "cliui": "^8.0.1",
-        "escalade": "^3.1.1",
-        "get-caller-file": "^2.0.5",
-        "require-directory": "^2.1.1",
-        "string-width": "^4.2.3",
-        "y18n": "^5.0.5",
-        "yargs-parser": "^21.1.1"
-      },
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/yargs-parser": {
-      "version": "21.1.1",
-      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
-      "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
-      "license": "ISC",
-      "engines": {
-        "node": ">=12"
-      }
-    }
-  }
-}
diff --git a/src/ci/package.json b/src/ci/package.json
deleted file mode 100644
index 91f21e5531e..00000000000
--- a/src/ci/package.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "dependencies": {
-    "@datadog/datadog-ci": "^2.45.1"
-  }
-}
diff --git a/src/ci/scripts/upload-build-metrics.py b/src/ci/scripts/upload-build-metrics.py
deleted file mode 100644
index 915ba953984..00000000000
--- a/src/ci/scripts/upload-build-metrics.py
+++ /dev/null
@@ -1,86 +0,0 @@
-"""
-This script postprocesses data gathered during a CI run, computes certain metrics
-from them, and uploads these metrics to DataDog.
-
-This script is expected to be executed from within a GitHub Actions job.
-
-It expects the following environment variables:
-- DATADOG_SITE: path to the DataDog API endpoint
-- DATADOG_API_KEY: DataDog API token
-- DD_GITHUB_JOB_NAME: Name of the current GitHub Actions job
-
-It expects the presence of a binary called `datadog-ci` inside `node_modules`.
-It can be installed with `npm ci` at `src/ci`.
-
-Usage:
-```bash
-$ python3 upload-build-metrics.py <path-to-CPU-usage-CSV>
-```
-
-`path-to-CPU-usage-CSV` is a path to a CSV generated by the `src/ci/cpu-usage-over-time.py` script.
-"""
-
-import argparse
-import csv
-import os
-import subprocess
-import sys
-from pathlib import Path
-from typing import List
-
-
-def load_cpu_usage(path: Path) -> List[float]:
-    usage = []
-    with open(path) as f:
-        reader = csv.reader(f, delimiter=",")
-        for row in reader:
-            # The log might contain incomplete rows or some Python exception
-            if len(row) == 2:
-                try:
-                    idle = float(row[1])
-                    usage.append(100.0 - idle)
-                except ValueError:
-                    pass
-    return usage
-
-
-def upload_datadog_measure(name: str, value: float):
-    """
-    Uploads a single numeric metric for the current GitHub Actions job to DataDog.
-    """
-    print(f"Metric {name}: {value:.4f}")
-
-    cmd = "npx"
-    if os.getenv("GITHUB_ACTIONS") is not None and sys.platform.lower().startswith(
-        "win"
-    ):
-        # Due to weird interaction of MSYS2 and Python, we need to use an absolute path,
-        # and also specify the ".cmd" at the end. See https://github.com/rust-lang/rust/pull/125771.
-        cmd = "C:\\Program Files\\nodejs\\npx.cmd"
-
-    subprocess.run(
-        [
-            cmd,
-            "datadog-ci",
-            "measure",
-            "--level",
-            "job",
-            "--measures",
-            f"{name}:{value}",
-        ],
-        check=False,
-    )
-
-
-if __name__ == "__main__":
-    parser = argparse.ArgumentParser(prog="DataDog metric uploader")
-    parser.add_argument("cpu-usage-history-csv")
-    args = parser.parse_args()
-
-    build_usage_csv = vars(args)["cpu-usage-history-csv"]
-    usage_timeseries = load_cpu_usage(Path(build_usage_csv))
-    if len(usage_timeseries) > 0:
-        avg_cpu_usage = sum(usage_timeseries) / len(usage_timeseries)
-    else:
-        avg_cpu_usage = 0
-    upload_datadog_measure("avg-cpu-usage", avg_cpu_usage)
diff --git a/src/doc/rustc-dev-guide/src/building/optimized-build.md b/src/doc/rustc-dev-guide/src/building/optimized-build.md
index 8feda59829b..f8ca1d0dc39 100644
--- a/src/doc/rustc-dev-guide/src/building/optimized-build.md
+++ b/src/doc/rustc-dev-guide/src/building/optimized-build.md
@@ -126,4 +126,4 @@ Here is an example of how can `opt-dist` be used locally (outside of CI):
 [`Environment`]: https://github.com/rust-lang/rust/blob/ee451f8faccf3050c76cdcd82543c917b40c7962/src/tools/opt-dist/src/environment.rs#L5
 
 > Note: if you want to run the actual CI pipeline, instead of running `opt-dist` locally,
-> you can execute `python3 src/ci/github-actions/ci.py run-local dist-x86_64-linux`.
+> you can execute `cargo run --manifest-path src/ci/citool/Cargo.toml run-local dist-x86_64-linux`.
diff --git a/src/doc/rustc-dev-guide/src/parallel-rustc.md b/src/doc/rustc-dev-guide/src/parallel-rustc.md
index c5b70706a81..690fb19c9f5 100644
--- a/src/doc/rustc-dev-guide/src/parallel-rustc.md
+++ b/src/doc/rustc-dev-guide/src/parallel-rustc.md
@@ -46,10 +46,8 @@ are implemented differently depending on whether `parallel-compiler` is true.
 
 | data structure                   | parallel                                            | non-parallel |
 | -------------------------------- | --------------------------------------------------- | ------------ |
-| OnceCell                         | std::sync::OnceLock                                 | std::cell::OnceCell |
 | Lock\<T> | (parking_lot::Mutex\<T>) | (std::cell::RefCell) |
 | RwLock\<T> | (parking_lot::RwLock\<T>) | (std::cell::RefCell) |
-| MTRef<'a, T> | &'a T | &'a mut T |
 | MTLock\<T> | (Lock\<T>) | (T) |
 | ReadGuard | parking_lot::RwLockReadGuard | std::cell::Ref |
 | MappedReadGuard | parking_lot::MappedRwLockReadGuard | std::cell::Ref |
diff --git a/src/doc/rustc-dev-guide/src/tests/ci.md b/src/doc/rustc-dev-guide/src/tests/ci.md
index a4b22392f19..ae6adb678af 100644
--- a/src/doc/rustc-dev-guide/src/tests/ci.md
+++ b/src/doc/rustc-dev-guide/src/tests/ci.md
@@ -28,7 +28,7 @@ Our CI is primarily executed on [GitHub Actions], with a single workflow defined
 in [`.github/workflows/ci.yml`], which contains a bunch of steps that are
 unified for all CI jobs that we execute. When a commit is pushed to a
 corresponding branch or a PR, the workflow executes the
-[`src/ci/github-actions/ci.py`] script, which dynamically generates the specific CI
+[`src/ci/citool`] crate, which dynamically generates the specific CI
 jobs that should be executed. This script uses the [`jobs.yml`] file as an
 input, which contains a declarative configuration of all our CI jobs.
 
@@ -299,7 +299,7 @@ platform’s custom [Docker container]. This has a lot of advantages for us:
 - We can avoid reinstalling tools (like QEMU or the Android emulator) every time
   thanks to Docker image caching.
 - Users can run the same tests in the same environment locally by just running
-  `python3 src/ci/github-actions/ci.py run-local <job-name>`, which is awesome to debug failures. Note that there are only linux docker images available locally due to licensing and
+  `cargo run --manifest-path src/ci/citool/Cargo.toml run-local <job-name>`, which is awesome to debug failures. Note that there are only linux docker images available locally due to licensing and
   other restrictions.
 
 The docker images prefixed with `dist-` are used for building artifacts while
@@ -443,7 +443,7 @@ this:
 [GitHub Actions]: https://github.com/rust-lang/rust/actions
 [`jobs.yml`]: https://github.com/rust-lang/rust/blob/master/src/ci/github-actions/jobs.yml
 [`.github/workflows/ci.yml`]: https://github.com/rust-lang/rust/blob/master/.github/workflows/ci.yml
-[`src/ci/github-actions/ci.py`]: https://github.com/rust-lang/rust/blob/master/src/ci/github-actions/ci.py
+[`src/ci/citool`]: https://github.com/rust-lang/rust/blob/master/src/ci/citool
 [rust-lang-ci]: https://github.com/rust-lang-ci/rust/actions
 [bors]: https://github.com/bors
 [homu]: https://github.com/rust-lang/homu
diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md
index 459c082906e..2905e470fab 100644
--- a/src/doc/rustc-dev-guide/src/tests/compiletest.md
+++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md
@@ -74,8 +74,7 @@ The following test suites are available, with links for more information:
 
 ### General purpose test suite
 
-[`run-make`](#run-make-tests) are general purpose tests using Rust programs (or
-Makefiles (legacy)).
+[`run-make`](#run-make-tests) are general purpose tests using Rust programs.
 
 ### Rustdoc test suites
 
@@ -396,14 +395,6 @@ your test, causing separate files to be generated for 32bit and 64bit systems.
 
 ### `run-make` tests
 
-> **Note on phasing out `Makefile`s**
-> 
-> We are planning to migrate all existing Makefile-based `run-make` tests
-> to Rust programs. You should not be adding new Makefile-based `run-make`
-> tests.
->
-> See <https://github.com/rust-lang/rust/issues/121876>.
-
 The tests in [`tests/run-make`] are general-purpose tests using Rust *recipes*,
 which are small programs (`rmake.rs`) allowing arbitrary Rust code such as
 `rustc` invocations, and is supported by a [`run_make_support`] library. Using
@@ -424,11 +415,6 @@ Compiletest directives like `//@ only-<target>` or `//@ ignore-<target>` are
 supported in `rmake.rs`, like in UI tests. However, revisions or building
 auxiliary via directives are not currently supported.
 
-Two `run-make` tests are ported over to Rust recipes as examples:
-
-- <https://github.com/rust-lang/rust/tree/master/tests/run-make/CURRENT_RUSTC_VERSION>
-- <https://github.com/rust-lang/rust/tree/master/tests/run-make/a-b-a-linker-guard>
-
 #### Quickly check if `rmake.rs` tests can be compiled
 
 You can quickly check if `rmake.rs` tests can be compiled without having to
@@ -481,20 +467,6 @@ Then add a corresponding entry to `"rust-analyzer.linkedProjects"`
 ],
 ```
 
-#### Using Makefiles (legacy)
-
-<div class="warning">
-You should avoid writing new Makefile-based `run-make` tests.
-</div>
-
-Each test should be in a separate directory with a `Makefile` indicating the
-commands to run.
-
-There is a [`tools.mk`] Makefile which you can include which provides a bunch of
-utilities to make it easier to run commands and compare outputs. Take a look at
-some of the other tests for some examples on how to get started.
-
-[`tools.mk`]: https://github.com/rust-lang/rust/blob/master/tests/run-make/tools.mk
 [`tests/run-make`]: https://github.com/rust-lang/rust/tree/master/tests/run-make
 [`run_make_support`]: https://github.com/rust-lang/rust/tree/master/src/tools/run-make-support
 
diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md
index 00bb2bc4dbb..14f18a7ecf7 100644
--- a/src/doc/rustc-dev-guide/src/tests/directives.md
+++ b/src/doc/rustc-dev-guide/src/tests/directives.md
@@ -6,10 +6,7 @@
 FIXME(jieyouxu) completely revise this chapter.
 -->
 
-Directives are special comments that tell compiletest how to build and interpret
-a test. They must appear before the Rust source in the test. They may also
-appear in `rmake.rs` or legacy Makefiles for [run-make
-tests](compiletest.md#run-make-tests).
+Directives are special comments that tell compiletest how to build and interpret a test. They must appear before the Rust source in the test. They may also appear in `rmake.rs` [run-make tests](compiletest.md#run-make-tests).
 
 They are normally put after the short comment that explains the point of this
 test. Compiletest test suites use `//@` to signal that a comment is a directive.
@@ -142,6 +139,7 @@ Some examples of `X` in `ignore-X` or `only-X`:
   matches that target as well as the emscripten targets.
 - Pointer width: `32bit`, `64bit`
 - Endianness: `endian-big`
+- Binary format: `elf`
 - Stage: `stage0`, `stage1`, `stage2`
 - Channel: `stable`, `beta`
 - When cross compiling: `cross-compile`
@@ -221,8 +219,6 @@ The following directives will check LLVM support:
     [`aarch64-gnu-debug`]), which only runs a
     subset of `run-make` tests. Other tests with this directive will not
     run at all, which is usually not what you want.
-  - Notably, the [`aarch64-gnu-debug`] CI job *currently* only runs `run-make`
-    tests which additionally contain `clang` in their test name.
 
 See also [Debuginfo tests](compiletest.md#debuginfo-tests) for directives for
 ignoring debuggers.
diff --git a/src/doc/rustc-dev-guide/src/tests/docker.md b/src/doc/rustc-dev-guide/src/tests/docker.md
index 2ca08d42130..a8a388ef90c 100644
--- a/src/doc/rustc-dev-guide/src/tests/docker.md
+++ b/src/doc/rustc-dev-guide/src/tests/docker.md
@@ -53,6 +53,15 @@ Some additional notes about using the interactive mode:
   containers. With the container name, run `docker exec -it <CONTAINER>
   /bin/bash` where `<CONTAINER>` is the container name like `4ba195e95cef`.
 
+The approach described above is a relatively low-level interface for running the Docker images
+directly. If you want to run a full CI Linux job locally with Docker, in a way that is as close to CI as possible, you can use the following command:
+
+```bash
+cargo run --manifest-path src/ci/citool/Cargo.toml run-local <job-name>
+# For example:
+cargo run --manifest-path src/ci/citool/Cargo.toml run-local dist-x86_64-linux-alt
+```
+
 [Docker]: https://www.docker.com/
 [`src/ci/docker`]: https://github.com/rust-lang/rust/tree/master/src/ci/docker
 [`src/ci/docker/run.sh`]: https://github.com/rust-lang/rust/blob/master/src/ci/docker/run.sh
diff --git a/src/doc/rustc-dev-guide/src/tests/running.md b/src/doc/rustc-dev-guide/src/tests/running.md
index 6ce65092389..9ddf0afee0c 100644
--- a/src/doc/rustc-dev-guide/src/tests/running.md
+++ b/src/doc/rustc-dev-guide/src/tests/running.md
@@ -238,30 +238,6 @@ This is much faster, but doesn't always work. For example, some tests include
 directives that specify specific compiler flags, or which rely on other crates,
 and they may not run the same without those options.
 
-## Running `run-make` tests
-
-### Windows
-
-Running the `run-make` test suite on Windows is a currently bit more involved.
-There are numerous prerequisites and environmental requirements:
-
-- Install msys2: <https://www.msys2.org/>
-- Specify `MSYS2_PATH_TYPE=inherit` in `msys2.ini` in the msys2 installation directory, run the
-  following with `MSYS2 MSYS`:
-  - `pacman -Syuu`
-  - `pacman -S make`
-  - `pacman -S diffutils`
-  - `pacman -S binutils`
-  - `./x test run-make` (`./x test tests/run-make` doesn't work)
-
-There is [on-going work][port-run-make] to not rely on `Makefile`s in the
-run-make test suite. Once this work is completed, you can run the entire
-`run-make` test suite on native Windows inside `cmd` or `PowerShell` without
-needing to install and use MSYS2. As of <!--date-check --> Oct 2024, it is
-already possible to run the vast majority of the `run-make` test suite outside
-of MSYS2, but there will be failures for the tests that still use `Makefile`s
-due to not finding `make`.
-
 ## Running tests on a remote machine
 
 Tests may be run on a remote machine (e.g. to test builds for a different
@@ -406,4 +382,3 @@ If you encounter bugs or problems, don't hesitate to open issues on the
 repository](https://github.com/rust-lang/rustc_codegen_gcc/).
 
 [`tests/ui`]: https://github.com/rust-lang/rust/tree/master/tests/ui
-[port-run-make]: https://github.com/rust-lang/rust/issues/121876
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index 6c7cdec3480..d9c2f6b28a7 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -50,6 +50,7 @@
     - [\*-linux-ohos](platform-support/openharmony.md)
     - [\*-hurd-gnu](platform-support/hurd.md)
     - [aarch64-unknown-teeos](platform-support/aarch64-unknown-teeos.md)
+    - [avr-none](platform-support/avr-none.md)
     - [\*-espidf](platform-support/esp-idf.md)
     - [\*-unknown-fuchsia](platform-support/fuchsia.md)
     - [\*-unknown-trusty](platform-support/trusty.md)
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index c4e5c1aac2f..dd085f916b9 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -301,7 +301,7 @@ target | std | host | notes
 [`armv8r-none-eabihf`](platform-support/armv8r-none-eabihf.md) | * |  | Bare Armv8-R, hardfloat
 [`armv7a-nuttx-eabi`](platform-support/nuttx.md) | ✓ |  | ARMv7-A with NuttX
 [`armv7a-nuttx-eabihf`](platform-support/nuttx.md) | ✓ |  | ARMv7-A with NuttX, hardfloat
-`avr-none` | * |  | AVR; requires `-Zbuild-std=core` and `-Ctarget-cpu=...`
+[`avr-none`](platform-support/avr-none.md) | * |  | AVR; requires `-Zbuild-std=core` and `-Ctarget-cpu=...`
 `bpfeb-unknown-none` | * |  | BPF (big endian)
 `bpfel-unknown-none` | * |  | BPF (little endian)
 `csky-unknown-linux-gnuabiv2` | ✓ |  | C-SKY abiv2 Linux (little endian)
diff --git a/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-gnu.md b/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-gnu.md
index b57083980d2..dda2a50c33d 100644
--- a/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-gnu.md
+++ b/src/doc/rustc/src/platform-support/riscv64gc-unknown-linux-gnu.md
@@ -65,7 +65,7 @@ section below.
 
 A RISC-V toolchain can be obtained for Windows/Mac/Linux from the
 [`riscv-gnu-toolchain`](https://github.com/riscv-collab/riscv-gnu-toolchain)
-repostory. Binaries are available via
+repository. Binaries are available via
 [embecosm](https://www.embecosm.com/resources/tool-chain-downloads/#riscv-linux),
 and may also be available from your OS's package manager.
 
diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md b/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md
index 994c0f4bbb3..1b0a312ca9c 100644
--- a/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md
+++ b/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md
@@ -100,7 +100,7 @@ This target is not a stable target. This means that there are a few engines
 which implement the `wasi-threads` feature and if they do they're likely behind a
 flag, for example:
 
-* Wasmtime - `--wasm-features=threads --wasi-modules=experimental-wasi-threads`
+* Wasmtime - `--wasi threads`
 * [WAMR](https://github.com/bytecodealliance/wasm-micro-runtime) - needs to be built with WAMR_BUILD_LIB_WASI_THREADS=1
 
 ## Building the target
diff --git a/src/doc/rustc/src/platform-support/wasm64-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm64-unknown-unknown.md
index 6932e6a5764..a717f5dad79 100644
--- a/src/doc/rustc/src/platform-support/wasm64-unknown-unknown.md
+++ b/src/doc/rustc/src/platform-support/wasm64-unknown-unknown.md
@@ -36,7 +36,7 @@ which implement the `memory64` feature and if they do they're likely behind a
 flag, for example:
 
 * Nodejs - `--experimental-wasm-memory64`
-* Wasmtime - `--wasm-features memory64`
+* Wasmtime - `--wasm memory64`
 
 Also note that at this time the `wasm64-unknown-unknown` target assumes the
 presence of other merged wasm proposals such as (with their LLVM feature flags):
diff --git a/src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md b/src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md
deleted file mode 100644
index 310c8d96294..00000000000
--- a/src/doc/unstable-book/src/language-features/unsized-tuple-coercion.md
+++ /dev/null
@@ -1,27 +0,0 @@
-# `unsized_tuple_coercion`
-
-The tracking issue for this feature is: [#42877]
-
-[#42877]: https://github.com/rust-lang/rust/issues/42877
-
-------------------------
-
-This is a part of [RFC0401]. According to the RFC, there should be an implementation like this:
-
-```rust,ignore (partial-example)
-impl<..., T, U: ?Sized> Unsized<(..., U)> for (..., T) where T: Unsized<U> {}
-```
-
-This implementation is currently gated behind `#[feature(unsized_tuple_coercion)]` to avoid insta-stability. Therefore you can use it like this:
-
-```rust
-#![feature(unsized_tuple_coercion)]
-
-fn main() {
-    let x : ([i32; 3], [i32; 3]) = ([1, 2, 3], [4, 5, 6]);
-    let y : &([i32; 3], [i32]) = &x;
-    assert_eq!(y.1[0], 4);
-}
-```
-
-[RFC0401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
diff --git a/src/etc/htmldocck.py b/src/etc/htmldocck.py
index d6b594aca71..06fc6518e3b 100755
--- a/src/etc/htmldocck.py
+++ b/src/etc/htmldocck.py
@@ -297,10 +297,24 @@ LINE_PATTERN = re.compile(
     re.X | re.UNICODE,
 )
 
+DEPRECATED_LINE_PATTERN = re.compile(
+    r"""
+    //\s+@
+""",
+    re.X | re.UNICODE,
+)
+
 
 def get_commands(template):
     with io.open(template, encoding="utf-8") as f:
         for lineno, line in concat_multi_lines(f):
+            if DEPRECATED_LINE_PATTERN.search(line):
+                print_err(
+                    lineno,
+                    line,
+                    "Deprecated command syntax, replace `// @` with `//@ `",
+                )
+                continue
             m = LINE_PATTERN.search(line)
             if not m:
                 continue
diff --git a/src/etc/pre-push.sh b/src/etc/pre-push.sh
index 6f86c7ab8a4..7bacc943f25 100755
--- a/src/etc/pre-push.sh
+++ b/src/etc/pre-push.sh
@@ -7,6 +7,20 @@
 
 set -Euo pipefail
 
+# Check if the push is doing anything other than deleting remote branches
+SKIP=true
+while read LOCAL_REF LOCAL_SHA REMOTE_REF REMOTE_SHA; do
+    if [[ "$LOCAL_REF" != "(delete)" || \
+          "$LOCAL_SHA" != "0000000000000000000000000000000000000000" ]]; then
+        SKIP=false
+    fi
+done
+
+if $SKIP; then
+    echo "Skipping tidy check for branch deletion"
+    exit 0
+fi
+
 ROOT_DIR="$(git rev-parse --show-toplevel)"
 
 echo "Running pre-push script $ROOT_DIR/x test tidy"
diff --git a/src/etc/test-float-parse/src/gen/exhaustive.rs b/src/etc/test-float-parse/src/gen/exhaustive.rs
index 5d4b6df8e59..01458fb0b60 100644
--- a/src/etc/test-float-parse/src/gen/exhaustive.rs
+++ b/src/etc/test-float-parse/src/gen/exhaustive.rs
@@ -13,13 +13,12 @@ impl<F: Float> Generator<F> for Exhaustive<F>
 where
     RangeInclusive<F::Int>: Iterator<Item = F::Int>,
 {
-    const NAME: &'static str = "exhaustive";
     const SHORT_NAME: &'static str = "exhaustive";
 
     type WriteCtx = F;
 
     fn total_tests() -> u64 {
-        F::Int::MAX.try_into().unwrap_or(u64::MAX)
+        1u64.checked_shl(F::Int::BITS).expect("More than u64::MAX tests")
     }
 
     fn new() -> Self {
diff --git a/src/etc/test-float-parse/src/gen/fuzz.rs b/src/etc/test-float-parse/src/gen/fuzz.rs
index 0c63e8aae26..7fc999d1671 100644
--- a/src/etc/test-float-parse/src/gen/fuzz.rs
+++ b/src/etc/test-float-parse/src/gen/fuzz.rs
@@ -49,7 +49,6 @@ impl<F: Float> Generator<F> for Fuzz<F>
 where
     Standard: Distribution<<F as Float>::Int>,
 {
-    const NAME: &'static str = "fuzz";
     const SHORT_NAME: &'static str = "fuzz";
 
     type WriteCtx = F;
diff --git a/src/etc/test-float-parse/src/gen/sparse.rs b/src/etc/test-float-parse/src/gen/sparse.rs
index 389b71056a3..72b65d4ce7f 100644
--- a/src/etc/test-float-parse/src/gen/sparse.rs
+++ b/src/etc/test-float-parse/src/gen/sparse.rs
@@ -35,7 +35,6 @@ impl<F: Float> Generator<F> for FewOnesInt<F>
 where
     <F::Int as TryFrom<u128>>::Error: std::fmt::Debug,
 {
-    const NAME: &'static str = "few ones int";
     const SHORT_NAME: &'static str = "few ones int";
 
     type WriteCtx = F::Int;
diff --git a/src/etc/test-float-parse/src/lib.rs b/src/etc/test-float-parse/src/lib.rs
index 3c71b0dc32e..def66398d9f 100644
--- a/src/etc/test-float-parse/src/lib.rs
+++ b/src/etc/test-float-parse/src/lib.rs
@@ -2,19 +2,19 @@ mod traits;
 mod ui;
 mod validate;
 
-use std::any::{TypeId, type_name};
+use std::any::type_name;
 use std::cmp::min;
 use std::ops::RangeInclusive;
 use std::process::ExitCode;
+use std::sync::OnceLock;
 use std::sync::atomic::{AtomicU64, Ordering};
-use std::sync::{OnceLock, mpsc};
 use std::{fmt, time};
 
-use indicatif::{MultiProgress, ProgressBar};
 use rand::distributions::{Distribution, Standard};
 use rayon::prelude::*;
 use time::{Duration, Instant};
 use traits::{Float, Generator, Int};
+use validate::CheckError;
 
 /// Test generators.
 mod gen {
@@ -43,7 +43,7 @@ const HUGE_TEST_CUTOFF: u64 = 5_000_000;
 /// Seed for tests that use a deterministic RNG.
 const SEED: [u8; 32] = *b"3.141592653589793238462643383279";
 
-/// Global configuration
+/// Global configuration.
 #[derive(Debug)]
 pub struct Config {
     pub timeout: Duration,
@@ -104,9 +104,9 @@ pub fn run(cfg: Config, include: &[String], exclude: &[String]) -> ExitCode {
         println!("Skipping test '{exc}'");
     }
 
-    println!("launching");
+    println!("Launching all");
     let elapsed = launch_tests(&mut tests, &cfg);
-    ui::finish(&tests, elapsed, &cfg)
+    ui::finish_all(&tests, elapsed, &cfg)
 }
 
 /// Enumerate tests to run but don't actually run them.
@@ -160,18 +160,18 @@ where
 #[derive(Debug)]
 pub struct TestInfo {
     pub name: String,
-    /// Tests are identified by the type ID of `(F, G)` (tuple of the float and generator type).
-    /// This gives an easy way to associate messages with tests.
-    id: TypeId,
     float_name: &'static str,
+    float_bits: u32,
     gen_name: &'static str,
     /// Name for display in the progress bar.
     short_name: String,
+    /// Pad the short name to a common width for progress bar use.
+    short_name_padded: String,
     total_tests: u64,
     /// Function to launch this test.
-    launch: fn(&mpsc::Sender<Msg>, &TestInfo, &Config),
+    launch: fn(&TestInfo, &Config),
     /// Progress bar to be updated.
-    pb: Option<ProgressBar>,
+    progress: Option<ui::Progress>,
     /// Once completed, this will be set.
     completed: OnceLock<Completed>,
 }
@@ -187,14 +187,18 @@ impl TestInfo {
         let f_name = type_name::<F>();
         let gen_name = G::NAME;
         let gen_short_name = G::SHORT_NAME;
+        let name = format!("{f_name} {gen_name}");
+        let short_name = format!("{f_name} {gen_short_name}");
+        let short_name_padded = format!("{short_name:18}");
 
         let info = TestInfo {
-            id: TypeId::of::<(F, G)>(),
             float_name: f_name,
+            float_bits: F::BITS,
             gen_name,
-            pb: None,
-            name: format!("{f_name} {gen_name}"),
-            short_name: format!("{f_name} {gen_short_name}"),
+            progress: None,
+            name,
+            short_name_padded,
+            short_name,
             launch: test_runner::<F, G>,
             total_tests: G::total_tests(),
             completed: OnceLock::new(),
@@ -202,106 +206,18 @@ impl TestInfo {
         v.push(info);
     }
 
-    /// Pad the short name to a common width for progress bar use.
-    fn short_name_padded(&self) -> String {
-        format!("{:18}", self.short_name)
-    }
-
-    /// Create a progress bar for this test within a multiprogress bar.
-    fn register_pb(&mut self, mp: &MultiProgress, drop_bars: &mut Vec<ProgressBar>) {
-        self.pb = Some(ui::create_pb(mp, self.total_tests, &self.short_name_padded(), drop_bars));
-    }
-
-    /// When the test is finished, update progress bar messages and finalize.
-    fn finalize_pb(&self, c: &Completed) {
-        let pb = self.pb.as_ref().unwrap();
-        ui::finalize_pb(pb, &self.short_name_padded(), c);
-    }
-
     /// True if this should be run after all others.
     fn is_huge_test(&self) -> bool {
         self.total_tests >= HUGE_TEST_CUTOFF
     }
-}
-
-/// A message sent from test runner threads to the UI/log thread.
-#[derive(Clone, Debug)]
-struct Msg {
-    id: TypeId,
-    update: Update,
-}
 
-impl Msg {
-    /// Wrap an `Update` into a message for the specified type. We use the `TypeId` of `(F, G)` to
-    /// identify which test a message in the channel came from.
-    fn new<F: Float, G: Generator<F>>(u: Update) -> Self {
-        Self { id: TypeId::of::<(F, G)>(), update: u }
-    }
-
-    /// Get the matching test from a list. Panics if not found.
-    fn find_test<'a>(&self, tests: &'a [TestInfo]) -> &'a TestInfo {
-        tests.iter().find(|t| t.id == self.id).unwrap()
-    }
-
-    /// Update UI as needed for a single message received from the test runners.
-    fn handle(self, tests: &[TestInfo], mp: &MultiProgress) {
-        let test = self.find_test(tests);
-        let pb = test.pb.as_ref().unwrap();
-
-        match self.update {
-            Update::Started => {
-                mp.println(format!("Testing '{}'", test.name)).unwrap();
-            }
-            Update::Progress { executed, failures } => {
-                pb.set_message(format! {"{failures}"});
-                pb.set_position(executed);
-            }
-            Update::Failure { fail, input, float_res } => {
-                mp.println(format!(
-                    "Failure in '{}': {fail}. parsing '{input}'. Parsed as: {float_res}",
-                    test.name
-                ))
-                .unwrap();
-            }
-            Update::Completed(c) => {
-                test.finalize_pb(&c);
-
-                let prefix = match c.result {
-                    Ok(FinishedAll) => "Completed tests for",
-                    Err(EarlyExit::Timeout) => "Timed out",
-                    Err(EarlyExit::MaxFailures) => "Max failures reached for",
-                };
-
-                mp.println(format!(
-                    "{prefix} generator '{}' in {:?}. {} tests run, {} failures",
-                    test.name, c.elapsed, c.executed, c.failures
-                ))
-                .unwrap();
-                test.completed.set(c).unwrap();
-            }
-        };
+    /// When the test is finished, update progress bar messages and finalize.
+    fn complete(&self, c: Completed) {
+        self.progress.as_ref().unwrap().complete(&c, 0);
+        self.completed.set(c).unwrap();
     }
 }
 
-/// Status sent with a message.
-#[derive(Clone, Debug)]
-enum Update {
-    /// Starting a new test runner.
-    Started,
-    /// Completed a out of b tests.
-    Progress { executed: u64, failures: u64 },
-    /// Received a failed test.
-    Failure {
-        fail: CheckFailure,
-        /// String for which parsing was attempted.
-        input: Box<str>,
-        /// The parsed & decomposed `FloatRes`, already stringified so we don't need generics here.
-        float_res: Box<str>,
-    },
-    /// Exited with an unexpected condition.
-    Completed(Completed),
-}
-
 /// Result of an input did not parsing successfully.
 #[derive(Clone, Debug)]
 enum CheckFailure {
@@ -329,6 +245,10 @@ enum CheckFailure {
         /// two representable values.
         incorrect_midpoint_rounding: bool,
     },
+    /// String did not parse successfully.
+    ParsingFailed(Box<str>),
+    /// A panic was caught.
+    Panic(Box<str>),
 }
 
 impl fmt::Display for CheckFailure {
@@ -363,6 +283,8 @@ impl fmt::Display for CheckFailure {
                 }
                 Ok(())
             }
+            CheckFailure::ParsingFailed(e) => write!(f, "parsing failed: {e}"),
+            CheckFailure::Panic(e) => write!(f, "function panicked: {e}"),
         }
     }
 }
@@ -398,55 +320,21 @@ enum EarlyExit {
 /// This launches a main thread that receives messages and handlees UI updates, and uses the
 /// rest of the thread pool to execute the tests.
 fn launch_tests(tests: &mut [TestInfo], cfg: &Config) -> Duration {
-    // Run shorter tests first
-    tests.sort_unstable_by_key(|test| test.total_tests);
+    // Run shorter tests and smaller float types first.
+    tests.sort_unstable_by_key(|test| (test.total_tests, test.float_bits));
 
     for test in tests.iter() {
         println!("Launching test '{}'", test.name);
     }
 
-    // Configure progress bars
     let mut all_progress_bars = Vec::new();
-    let mp = MultiProgress::new();
-    mp.set_move_cursor(true);
-    for test in tests.iter_mut() {
-        test.register_pb(&mp, &mut all_progress_bars);
-    }
-
-    ui::set_panic_hook(all_progress_bars);
-
-    let (tx, rx) = mpsc::channel::<Msg>();
     let start = Instant::now();
 
-    rayon::scope(|scope| {
-        // Thread that updates the UI
-        scope.spawn(|_scope| {
-            let rx = rx; // move rx
-
-            loop {
-                if tests.iter().all(|t| t.completed.get().is_some()) {
-                    break;
-                }
-
-                let msg = rx.recv().unwrap();
-                msg.handle(tests, &mp);
-            }
-
-            // All tests completed; finish things up
-            drop(mp);
-            assert_eq!(rx.try_recv().unwrap_err(), mpsc::TryRecvError::Empty);
-        });
-
-        // Don't let the thread pool be starved by huge tests. Run faster tests first in parallel,
-        // then parallelize only within the rest of the tests.
-        let (huge_tests, normal_tests): (Vec<_>, Vec<_>) =
-            tests.iter().partition(|t| t.is_huge_test());
-
-        // Run the actual tests
-        normal_tests.par_iter().for_each(|test| ((test.launch)(&tx, test, cfg)));
-
-        huge_tests.par_iter().for_each(|test| ((test.launch)(&tx, test, cfg)));
-    });
+    for test in tests.iter_mut() {
+        test.progress = Some(ui::Progress::new(test, &mut all_progress_bars));
+        ui::set_panic_hook(&all_progress_bars);
+        ((test.launch)(test, cfg));
+    }
 
     start.elapsed()
 }
@@ -454,15 +342,12 @@ fn launch_tests(tests: &mut [TestInfo], cfg: &Config) -> Duration {
 /// Test runer for a single generator.
 ///
 /// This calls the generator's iterator multiple times (in parallel) and validates each output.
-fn test_runner<F: Float, G: Generator<F>>(tx: &mpsc::Sender<Msg>, _info: &TestInfo, cfg: &Config) {
-    tx.send(Msg::new::<F, G>(Update::Started)).unwrap();
-
-    let total = G::total_tests();
+fn test_runner<F: Float, G: Generator<F>>(test: &TestInfo, cfg: &Config) {
     let gen = G::new();
     let executed = AtomicU64::new(0);
     let failures = AtomicU64::new(0);
 
-    let checks_per_update = min(total, 1000);
+    let checks_per_update = min(test.total_tests, 1000);
     let started = Instant::now();
 
     // Function to execute for a single test iteration.
@@ -474,7 +359,12 @@ fn test_runner<F: Float, G: Generator<F>>(tx: &mpsc::Sender<Msg>, _info: &TestIn
         match validate::validate::<F>(buf) {
             Ok(()) => (),
             Err(e) => {
-                tx.send(Msg::new::<F, G>(e)).unwrap();
+                let CheckError { fail, input, float_res } = e;
+                test.progress.as_ref().unwrap().println(&format!(
+                    "Failure in '{}': {fail}. parsing '{input}'. Parsed as: {float_res}",
+                    test.name
+                ));
+
                 let f = failures.fetch_add(1, Ordering::Relaxed);
                 // End early if the limit is exceeded.
                 if f >= cfg.max_failures {
@@ -486,9 +376,7 @@ fn test_runner<F: Float, G: Generator<F>>(tx: &mpsc::Sender<Msg>, _info: &TestIn
         // Send periodic updates
         if executed % checks_per_update == 0 {
             let failures = failures.load(Ordering::Relaxed);
-
-            tx.send(Msg::new::<F, G>(Update::Progress { executed, failures })).unwrap();
-
+            test.progress.as_ref().unwrap().update(executed, failures);
             if started.elapsed() > cfg.timeout {
                 return Err(EarlyExit::Timeout);
             }
@@ -499,15 +387,19 @@ fn test_runner<F: Float, G: Generator<F>>(tx: &mpsc::Sender<Msg>, _info: &TestIn
 
     // Run the test iterations in parallel. Each thread gets a string buffer to write
     // its check values to.
-    let res = gen.par_bridge().try_for_each_init(|| String::with_capacity(100), check_one);
+    let res = gen.par_bridge().try_for_each_init(String::new, check_one);
 
     let elapsed = started.elapsed();
     let executed = executed.into_inner();
     let failures = failures.into_inner();
 
     // Warn about bad estimates if relevant.
-    let warning = if executed != total && res.is_ok() {
-        let msg = format!("executed tests != estimated ({executed} != {total}) for {}", G::NAME);
+    let warning = if executed != test.total_tests && res.is_ok() {
+        let msg = format!(
+            "executed tests != estimated ({executed} != {}) for {}",
+            test.total_tests,
+            G::NAME
+        );
 
         Some(msg.into())
     } else {
@@ -515,12 +407,5 @@ fn test_runner<F: Float, G: Generator<F>>(tx: &mpsc::Sender<Msg>, _info: &TestIn
     };
 
     let result = res.map(|()| FinishedAll);
-    tx.send(Msg::new::<F, G>(Update::Completed(Completed {
-        executed,
-        failures,
-        result,
-        warning,
-        elapsed,
-    })))
-    .unwrap();
+    test.complete(Completed { executed, failures, result, warning, elapsed });
 }
diff --git a/src/etc/test-float-parse/src/traits.rs b/src/etc/test-float-parse/src/traits.rs
index f5333d63b36..57e702b7d09 100644
--- a/src/etc/test-float-parse/src/traits.rs
+++ b/src/etc/test-float-parse/src/traits.rs
@@ -147,12 +147,12 @@ pub trait Float:
 }
 
 macro_rules! impl_float {
-    ($($fty:ty, $ity:ty, $bits:literal);+) => {
+    ($($fty:ty, $ity:ty);+) => {
         $(
             impl Float for $fty {
                 type Int = $ity;
                 type SInt = <Self::Int as Int>::Signed;
-                const BITS: u32 = $bits;
+                const BITS: u32 = <$ity>::BITS;
                 const MAN_BITS: u32 = Self::MANTISSA_DIGITS - 1;
                 const MAN_MASK: Self::Int = (Self::Int::ONE << Self::MAN_BITS) - Self::Int::ONE;
                 const SIGN_MASK: Self::Int = Self::Int::ONE << (Self::BITS-1);
@@ -168,7 +168,7 @@ macro_rules! impl_float {
     }
 }
 
-impl_float!(f32, u32, 32; f64, u64, 64);
+impl_float!(f32, u32; f64, u64);
 
 /// A test generator. Should provide an iterator that produces unique patterns to parse.
 ///
@@ -177,7 +177,7 @@ impl_float!(f32, u32, 32; f64, u64, 64);
 /// allocations (which otherwise turn out to be a pretty expensive part of these tests).
 pub trait Generator<F: Float>: Iterator<Item = Self::WriteCtx> + Send + 'static {
     /// Full display and filtering name
-    const NAME: &'static str;
+    const NAME: &'static str = Self::SHORT_NAME;
 
     /// Name for display with the progress bar
     const SHORT_NAME: &'static str;
diff --git a/src/etc/test-float-parse/src/ui.rs b/src/etc/test-float-parse/src/ui.rs
index f333bd4a55d..1ee57723e6a 100644
--- a/src/etc/test-float-parse/src/ui.rs
+++ b/src/etc/test-float-parse/src/ui.rs
@@ -1,67 +1,92 @@
 //! Progress bars and such.
 
+use std::any::type_name;
+use std::fmt;
 use std::io::{self, Write};
 use std::process::ExitCode;
 use std::time::Duration;
 
-use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
+use indicatif::{ProgressBar, ProgressStyle};
 
 use crate::{Completed, Config, EarlyExit, FinishedAll, TestInfo};
 
 /// Templates for progress bars.
-const PB_TEMPLATE: &str = "[{elapsed:3} {percent:3}%] {bar:20.cyan/blue} NAME ({pos}/{len}, {msg} f, {per_sec}, eta {eta})";
-const PB_TEMPLATE_FINAL: &str =
-    "[{elapsed:3} {percent:3}%] NAME ({pos}/{len}, {msg:.COLOR}, {per_sec}, {elapsed_precise})";
-
-/// Create a new progress bar within a multiprogress bar.
-pub fn create_pb(
-    mp: &MultiProgress,
-    total_tests: u64,
-    short_name_padded: &str,
-    all_bars: &mut Vec<ProgressBar>,
-) -> ProgressBar {
-    let pb = mp.add(ProgressBar::new(total_tests));
-    let pb_style = ProgressStyle::with_template(&PB_TEMPLATE.replace("NAME", short_name_padded))
-        .unwrap()
-        .progress_chars("##-");
-
-    pb.set_style(pb_style.clone());
-    pb.set_message("0");
-    all_bars.push(pb.clone());
-    pb
+const PB_TEMPLATE: &str = "[{elapsed:3} {percent:3}%] {bar:20.cyan/blue} NAME \
+        {human_pos:>8}/{human_len:8} {msg} f {per_sec:14} eta {eta:8}";
+const PB_TEMPLATE_FINAL: &str = "[{elapsed:3} {percent:3}%] {bar:20.cyan/blue} NAME \
+        {human_pos:>8}/{human_len:8} {msg:.COLOR} {per_sec:18} {elapsed_precise}";
+
+/// Thin abstraction over our usage of a `ProgressBar`.
+#[derive(Debug)]
+pub struct Progress {
+    pb: ProgressBar,
+    make_final_style: NoDebug<Box<dyn Fn(&'static str) -> ProgressStyle + Sync>>,
 }
 
-/// Removes the status bar and replace it with a message.
-pub fn finalize_pb(pb: &ProgressBar, short_name_padded: &str, c: &Completed) {
-    let f = c.failures;
+impl Progress {
+    /// Create a new progress bar within a multiprogress bar.
+    pub fn new(test: &TestInfo, all_bars: &mut Vec<ProgressBar>) -> Self {
+        let initial_template = PB_TEMPLATE.replace("NAME", &test.short_name_padded);
+        let final_template = PB_TEMPLATE_FINAL.replace("NAME", &test.short_name_padded);
+        let initial_style =
+            ProgressStyle::with_template(&initial_template).unwrap().progress_chars("##-");
+        let make_final_style = move |color| {
+            ProgressStyle::with_template(&final_template.replace("COLOR", color))
+                .unwrap()
+                .progress_chars("##-")
+        };
 
-    // Use a tuple so we can use colors
-    let (color, msg, finish_pb): (&str, String, fn(&ProgressBar, String)) = match &c.result {
-        Ok(FinishedAll) if f > 0 => {
-            ("red", format!("{f} f (finished with errors)",), ProgressBar::finish_with_message)
-        }
-        Ok(FinishedAll) => {
-            ("green", format!("{f} f (finished successfully)",), ProgressBar::finish_with_message)
-        }
-        Err(EarlyExit::Timeout) => {
-            ("red", format!("{f} f (timed out)"), ProgressBar::abandon_with_message)
+        let pb = ProgressBar::new(test.total_tests);
+        pb.set_style(initial_style);
+        pb.set_length(test.total_tests);
+        pb.set_message("0");
+        all_bars.push(pb.clone());
+
+        Progress { pb, make_final_style: NoDebug(Box::new(make_final_style)) }
+    }
+
+    /// Completed a out of b tests.
+    pub fn update(&self, completed: u64, failures: u64) {
+        // Infrequently update the progress bar.
+        if completed % 5_000 == 0 || failures > 0 {
+            self.pb.set_position(completed);
         }
-        Err(EarlyExit::MaxFailures) => {
-            ("red", format!("{f} f (failure limit)"), ProgressBar::abandon_with_message)
+
+        if failures > 0 {
+            self.pb.set_message(format! {"{failures}"});
         }
-    };
+    }
+
+    /// Finalize the progress bar.
+    pub fn complete(&self, c: &Completed, real_total: u64) {
+        let f = c.failures;
+        let (color, msg, finish_fn): (&str, String, fn(&ProgressBar)) = match &c.result {
+            Ok(FinishedAll) if f > 0 => {
+                ("red", format!("{f} f (completed with errors)",), ProgressBar::finish)
+            }
+            Ok(FinishedAll) => {
+                ("green", format!("{f} f (completed successfully)",), ProgressBar::finish)
+            }
+            Err(EarlyExit::Timeout) => ("red", format!("{f} f (timed out)"), ProgressBar::abandon),
+            Err(EarlyExit::MaxFailures) => {
+                ("red", format!("{f} f (failure limit)"), ProgressBar::abandon)
+            }
+        };
 
-    let pb_style = ProgressStyle::with_template(
-        &PB_TEMPLATE_FINAL.replace("NAME", short_name_padded).replace("COLOR", color),
-    )
-    .unwrap();
+        self.pb.set_position(real_total);
+        self.pb.set_style(self.make_final_style.0(color));
+        self.pb.set_message(msg);
+        finish_fn(&self.pb);
+    }
 
-    pb.set_style(pb_style);
-    finish_pb(pb, msg);
+    /// Print a message to stdout above the current progress bar.
+    pub fn println(&self, msg: &str) {
+        self.pb.suspend(|| println!("{msg}"));
+    }
 }
 
 /// Print final messages after all tests are complete.
-pub fn finish(tests: &[TestInfo], total_elapsed: Duration, cfg: &Config) -> ExitCode {
+pub fn finish_all(tests: &[TestInfo], total_elapsed: Duration, cfg: &Config) -> ExitCode {
     println!("\n\nResults:");
 
     let mut failed_generators = 0;
@@ -118,8 +143,9 @@ pub fn finish(tests: &[TestInfo], total_elapsed: Duration, cfg: &Config) -> Exit
 
 /// indicatif likes to eat panic messages. This workaround isn't ideal, but it improves things.
 /// <https://github.com/console-rs/indicatif/issues/121>.
-pub fn set_panic_hook(drop_bars: Vec<ProgressBar>) {
+pub fn set_panic_hook(drop_bars: &[ProgressBar]) {
     let hook = std::panic::take_hook();
+    let drop_bars = drop_bars.to_owned();
     std::panic::set_hook(Box::new(move |info| {
         for bar in &drop_bars {
             bar.abandon();
@@ -130,3 +156,13 @@ pub fn set_panic_hook(drop_bars: Vec<ProgressBar>) {
         hook(info);
     }));
 }
+
+/// Allow non-Debug items in a `derive(Debug)` struct`.
+#[derive(Clone)]
+struct NoDebug<T>(T);
+
+impl<T> fmt::Debug for NoDebug<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.write_str(type_name::<Self>())
+    }
+}
diff --git a/src/etc/test-float-parse/src/validate.rs b/src/etc/test-float-parse/src/validate.rs
index 1eb3699cfb9..40dda274e3b 100644
--- a/src/etc/test-float-parse/src/validate.rs
+++ b/src/etc/test-float-parse/src/validate.rs
@@ -1,6 +1,6 @@
 //! Everything related to verifying that parsed outputs are correct.
 
-use std::any::type_name;
+use std::any::{Any, type_name};
 use std::collections::BTreeMap;
 use std::ops::RangeInclusive;
 use std::str::FromStr;
@@ -9,7 +9,7 @@ use std::sync::LazyLock;
 use num::bigint::ToBigInt;
 use num::{BigInt, BigRational, FromPrimitive, Signed, ToPrimitive};
 
-use crate::{CheckFailure, Float, Int, Update};
+use crate::{CheckFailure, Float, Int};
 
 /// Powers of two that we store for constants. Account for binary128 which has a 15-bit exponent.
 const POWERS_OF_TWO_RANGE: RangeInclusive<i32> = (-(2 << 15))..=(2 << 15);
@@ -89,10 +89,16 @@ impl Constants {
 }
 
 /// Validate that a string parses correctly
-pub fn validate<F: Float>(input: &str) -> Result<(), Update> {
-    let parsed: F = input
-        .parse()
-        .unwrap_or_else(|e| panic!("parsing failed for {}: {e}. Input: {input}", type_name::<F>()));
+pub fn validate<F: Float>(input: &str) -> Result<(), CheckError> {
+    // Catch panics in case debug assertions within `std` fail.
+    let parsed = std::panic::catch_unwind(|| {
+        input.parse::<F>().map_err(|e| CheckError {
+            fail: CheckFailure::ParsingFailed(e.to_string().into()),
+            input: input.into(),
+            float_res: "none".into(),
+        })
+    })
+    .map_err(|e| convert_panic_error(&e, input))??;
 
     // Parsed float, decoded into significand and exponent
     let decoded = decode(parsed);
@@ -104,6 +110,21 @@ pub fn validate<F: Float>(input: &str) -> Result<(), Update> {
     decoded.check(rational, input)
 }
 
+/// Turn panics into concrete error types.
+fn convert_panic_error(e: &dyn Any, input: &str) -> CheckError {
+    let msg = e
+        .downcast_ref::<String>()
+        .map(|s| s.as_str())
+        .or_else(|| e.downcast_ref::<&str>().copied())
+        .unwrap_or("(no contents)");
+
+    CheckError {
+        fail: CheckFailure::Panic(msg.into()),
+        input: input.into(),
+        float_res: "none".into(),
+    }
+}
+
 /// The result of parsing a string to a float type.
 #[derive(Clone, Copy, Debug, PartialEq)]
 pub enum FloatRes<F: Float> {
@@ -118,10 +139,19 @@ pub enum FloatRes<F: Float> {
     },
 }
 
+#[derive(Clone, Debug)]
+pub struct CheckError {
+    pub fail: CheckFailure,
+    /// String for which parsing was attempted.
+    pub input: Box<str>,
+    /// The parsed & decomposed `FloatRes`, already stringified so we don't need generics here.
+    pub float_res: Box<str>,
+}
+
 impl<F: Float> FloatRes<F> {
     /// Given a known exact rational, check that this representation is accurate within the
     /// limits of the float representation. If not, construct a failure `Update` to send.
-    fn check(self, expected: Rational, input: &str) -> Result<(), Update> {
+    fn check(self, expected: Rational, input: &str) -> Result<(), CheckError> {
         let consts = F::constants();
         // let bool_helper = |cond: bool, err| cond.then_some(()).ok_or(err);
 
@@ -173,7 +203,7 @@ impl<F: Float> FloatRes<F> {
             (Rational::Finite(r), FloatRes::Real { sig, exp }) => Self::validate_real(r, sig, exp),
         };
 
-        res.map_err(|fail| Update::Failure {
+        res.map_err(|fail| CheckError {
             fail,
             input: input.into(),
             float_res: format!("{self:?}").into(),
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index 91cc4088788..909b81a723b 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "rustdoc"
 version = "0.0.0"
-edition = "2021"
+edition = "2024"
 build = "build.rs"
 
 [lib]
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index bec7fbe8f52..ab169f3c2a4 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -48,12 +48,12 @@ impl Cfg {
         exclude: &FxHashSet<Cfg>,
     ) -> Result<Option<Cfg>, InvalidCfgError> {
         match nested_cfg {
-            MetaItemInner::MetaItem(ref cfg) => Cfg::parse_without(cfg, exclude),
+            MetaItemInner::MetaItem(cfg) => Cfg::parse_without(cfg, exclude),
             MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => match *b {
                 true => Ok(Some(Cfg::True)),
                 false => Ok(Some(Cfg::False)),
             },
-            MetaItemInner::Lit(ref lit) => {
+            MetaItemInner::Lit(lit) => {
                 Err(InvalidCfgError { msg: "unexpected literal", span: lit.span })
             }
         }
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index ceffe5e5ce0..bb12e4a706e 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -741,7 +741,7 @@ pub(crate) fn clean_generics<'tcx>(
     for p in gens.params.iter().filter(|p| !is_impl_trait(p) && !is_elided_lifetime(p)) {
         let mut p = clean_generic_param(cx, Some(gens), p);
         match &mut p.kind {
-            GenericParamDefKind::Lifetime { ref mut outlives } => {
+            GenericParamDefKind::Lifetime { outlives } => {
                 if let Some(region_pred) = region_predicates.get_mut(&Lifetime(p.name)) {
                     // We merge bounds in the `where` clause.
                     for outlive in outlives.drain(..) {
@@ -2688,7 +2688,7 @@ fn filter_doc_attr_ident(ident: Symbol, is_inline: bool) -> bool {
 /// Before calling this function, make sure `normal` is a `#[doc]` attribute.
 fn filter_doc_attr(args: &mut hir::AttrArgs, is_inline: bool) {
     match args {
-        hir::AttrArgs::Delimited(ref mut args) => {
+        hir::AttrArgs::Delimited(args) => {
             let tokens = filter_tokens_from_list(&args.tokens, |token| {
                 !matches!(
                     token,
diff --git a/src/librustdoc/clean/render_macro_matchers.rs b/src/librustdoc/clean/render_macro_matchers.rs
index 3cc5f8d615a..88db853d7c3 100644
--- a/src/librustdoc/clean/render_macro_matchers.rs
+++ b/src/librustdoc/clean/render_macro_matchers.rs
@@ -1,4 +1,4 @@
-use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw};
+use rustc_ast::token::{self, Delimiter, IdentIsRaw};
 use rustc_ast::tokenstream::{TokenStream, TokenTree};
 use rustc_ast_pretty::pprust::PrintState;
 use rustc_ast_pretty::pprust::state::State as Printer;
@@ -137,15 +137,10 @@ fn print_tts(printer: &mut Printer<'_>, tts: &TokenStream) {
                 (Dollar, token::Ident(..)) => (false, DollarIdent),
                 (DollarIdent, token::Colon) => (false, DollarIdentColon),
                 (DollarIdentColon, token::Ident(..)) => (false, Other),
-                (
-                    DollarParen,
-                    token::BinOp(BinOpToken::Plus | BinOpToken::Star) | token::Question,
-                ) => (false, Other),
+                (DollarParen, token::Plus | token::Star | token::Question) => (false, Other),
                 (DollarParen, _) => (false, DollarParenSep),
-                (DollarParenSep, token::BinOp(BinOpToken::Plus | BinOpToken::Star)) => {
-                    (false, Other)
-                }
-                (Pound, token::Not) => (false, PoundBang),
+                (DollarParenSep, token::Plus | token::Star) => (false, Other),
+                (Pound, token::Bang) => (false, PoundBang),
                 (_, token::Ident(symbol, IdentIsRaw::No))
                     if !usually_needs_space_between_keyword_and_open_delim(*symbol, tt.span) =>
                 {
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 178b6a60b41..5906a720e0f 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -502,7 +502,7 @@ impl Item {
         let Some(links) = cx.cache().intra_doc_links.get(&self.item_id) else { return vec![] };
         links
             .iter()
-            .filter_map(|ItemLink { link: s, link_text, page_id: id, ref fragment }| {
+            .filter_map(|ItemLink { link: s, link_text, page_id: id, fragment }| {
                 debug!(?id);
                 if let Ok((mut href, ..)) = href(*id, cx) {
                     debug!(?href);
@@ -1150,7 +1150,7 @@ pub(crate) struct Attributes {
 }
 
 impl Attributes {
-    pub(crate) fn lists(&self, name: Symbol) -> impl Iterator<Item = ast::MetaItemInner> + '_ {
+    pub(crate) fn lists(&self, name: Symbol) -> impl Iterator<Item = ast::MetaItemInner> {
         hir_attr_lists(&self.other_attrs[..], name)
     }
 
@@ -1864,7 +1864,7 @@ impl PrimitiveType {
             .copied()
     }
 
-    pub(crate) fn all_impls(tcx: TyCtxt<'_>) -> impl Iterator<Item = DefId> + '_ {
+    pub(crate) fn all_impls(tcx: TyCtxt<'_>) -> impl Iterator<Item = DefId> {
         Self::simplified_types()
             .values()
             .flatten()
@@ -2259,7 +2259,7 @@ impl GenericArgs {
             GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(),
         }
     }
-    pub(crate) fn constraints<'a>(&'a self) -> Box<dyn Iterator<Item = AssocItemConstraint> + 'a> {
+    pub(crate) fn constraints(&self) -> Box<dyn Iterator<Item = AssocItemConstraint> + '_> {
         match self {
             GenericArgs::AngleBracketed { constraints, .. } => {
                 Box::new(constraints.iter().cloned())
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 34656b26ce2..a284de5229a 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -60,7 +60,7 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
     let primitives = local_crate.primitives(cx.tcx);
     let keywords = local_crate.keywords(cx.tcx);
     {
-        let ItemKind::ModuleItem(ref mut m) = &mut module.inner.kind else { unreachable!() };
+        let ItemKind::ModuleItem(m) = &mut module.inner.kind else { unreachable!() };
         m.items.extend(primitives.iter().map(|&(def_id, prim)| {
             Item::from_def_id_and_parts(
                 def_id,
@@ -302,7 +302,7 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
     use rustc_hir::*;
     debug!("trying to get a name from pattern: {p:?}");
 
-    Symbol::intern(&match p.kind {
+    Symbol::intern(&match &p.kind {
         // FIXME(never_patterns): does this make sense?
         PatKind::Wild
         | PatKind::Err(_)
@@ -313,8 +313,9 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
         }
         PatKind::Binding(_, _, ident, _) => return ident.name,
         PatKind::Box(p) | PatKind::Ref(p, _) | PatKind::Guard(p, _) => return name_from_pat(p),
-        PatKind::TupleStruct(ref p, ..)
-        | PatKind::Expr(PatExpr { kind: PatExprKind::Path(ref p), .. }) => qpath_to_string(p),
+        PatKind::TupleStruct(p, ..) | PatKind::Expr(PatExpr { kind: PatExprKind::Path(p), .. }) => {
+            qpath_to_string(p)
+        }
         PatKind::Or(pats) => {
             fmt::from_fn(|f| pats.iter().map(|p| name_from_pat(p)).joined(" | ", f)).to_string()
         }
@@ -329,7 +330,7 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
             return Symbol::intern("()");
         }
         PatKind::Slice(begin, mid, end) => {
-            fn print_pat<'a>(pat: &'a Pat<'a>, wild: bool) -> impl Display + 'a {
+            fn print_pat(pat: &Pat<'_>, wild: bool) -> impl Display {
                 fmt::from_fn(move |f| {
                     if wild {
                         f.write_str("..")?;
@@ -493,7 +494,7 @@ pub(crate) fn resolve_type(cx: &mut DocContext<'_>, path: Path) -> Type {
 pub(crate) fn synthesize_auto_trait_and_blanket_impls(
     cx: &mut DocContext<'_>,
     item_def_id: DefId,
-) -> impl Iterator<Item = Item> {
+) -> impl Iterator<Item = Item> + use<> {
     let auto_impls = cx
         .sess()
         .prof
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index fd4d9845c89..e67fe6c88ea 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -315,23 +315,30 @@ pub(crate) enum ModuleSorting {
     Alphabetical,
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+#[derive(Clone, Debug, PartialEq, Eq)]
 pub(crate) enum EmitType {
     Unversioned,
     Toolchain,
     InvocationSpecific,
+    DepInfo(Option<PathBuf>),
 }
 
 impl FromStr for EmitType {
     type Err = ();
 
     fn from_str(s: &str) -> Result<Self, Self::Err> {
-        use EmitType::*;
         match s {
-            "unversioned-shared-resources" => Ok(Unversioned),
-            "toolchain-shared-resources" => Ok(Toolchain),
-            "invocation-specific" => Ok(InvocationSpecific),
-            _ => Err(()),
+            "unversioned-shared-resources" => Ok(Self::Unversioned),
+            "toolchain-shared-resources" => Ok(Self::Toolchain),
+            "invocation-specific" => Ok(Self::InvocationSpecific),
+            "dep-info" => Ok(Self::DepInfo(None)),
+            option => {
+                if let Some(file) = option.strip_prefix("dep-info=") {
+                    Ok(Self::DepInfo(Some(Path::new(file).into())))
+                } else {
+                    Err(())
+                }
+            }
         }
     }
 }
@@ -340,6 +347,15 @@ impl RenderOptions {
     pub(crate) fn should_emit_crate(&self) -> bool {
         self.emit.is_empty() || self.emit.contains(&EmitType::InvocationSpecific)
     }
+
+    pub(crate) fn dep_info(&self) -> Option<Option<&Path>> {
+        for emit in &self.emit {
+            if let EmitType::DepInfo(file) = emit {
+                return Some(file.as_deref());
+            }
+        }
+        None
+    }
 }
 
 /// Create the input (string or file path)
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 757a2a6e0dd..679921c3269 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -15,11 +15,12 @@ use rustc_hir::def::Res;
 use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{HirId, Path};
-use rustc_interface::interface;
 use rustc_lint::{MissingDoc, late_lint_mod};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
-use rustc_session::config::{self, CrateType, ErrorOutputType, Input, ResolveDocLinks};
+use rustc_session::config::{
+    self, CrateType, ErrorOutputType, Input, OutFileName, OutputType, OutputTypes, ResolveDocLinks,
+};
 pub(crate) use rustc_session::config::{Options, UnstableOptions};
 use rustc_session::{Session, lint};
 use rustc_span::source_map;
@@ -219,7 +220,7 @@ pub(crate) fn create_config(
         remap_path_prefix,
         ..
     }: RustdocOptions,
-    RenderOptions { document_private, .. }: &RenderOptions,
+    render_options: &RenderOptions,
 ) -> rustc_interface::Config {
     // Add the doc cfg into the doc build.
     cfgs.push("doc".to_string());
@@ -245,8 +246,11 @@ pub(crate) fn create_config(
 
     let crate_types =
         if proc_macro_crate { vec![CrateType::ProcMacro] } else { vec![CrateType::Rlib] };
-    let resolve_doc_links =
-        if *document_private { ResolveDocLinks::All } else { ResolveDocLinks::Exported };
+    let resolve_doc_links = if render_options.document_private {
+        ResolveDocLinks::All
+    } else {
+        ResolveDocLinks::Exported
+    };
     let test = scrape_examples_options.map(|opts| opts.scrape_tests).unwrap_or(false);
     // plays with error output here!
     let sessopts = config::Options {
@@ -269,10 +273,18 @@ pub(crate) fn create_config(
         crate_name,
         test,
         remap_path_prefix,
+        output_types: if let Some(file) = render_options.dep_info() {
+            OutputTypes::new(&[(
+                OutputType::DepInfo,
+                file.map(|f| OutFileName::Real(f.to_path_buf())),
+            )])
+        } else {
+            OutputTypes::new(&[])
+        },
         ..Options::default()
     };
 
-    interface::Config {
+    rustc_interface::Config {
         opts: sessopts,
         crate_cfg: cfgs,
         crate_check_cfg: check_cfgs,
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 91b4b3ba1eb..ea740508c58 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -15,7 +15,6 @@ use std::iter::{self, once};
 use itertools::Either;
 use rustc_abi::ExternAbi;
 use rustc_attr_parsing::{ConstStability, StabilityLevel, StableSince};
-use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
@@ -30,7 +29,7 @@ use super::url_parts_builder::{UrlPartsBuilder, estimate_item_path_byte_length};
 use crate::clean::types::ExternalLocation;
 use crate::clean::utils::find_nearest_parent_module;
 use crate::clean::{self, ExternalCrate, PrimitiveType};
-use crate::display::Joined as _;
+use crate::display::{Joined as _, MaybeDisplay as _};
 use crate::formats::cache::Cache;
 use crate::formats::item_type::ItemType;
 use crate::html::escape::{Escape, EscapeBodyText};
@@ -41,10 +40,10 @@ pub(crate) fn write_str(s: &mut String, f: fmt::Arguments<'_>) {
     s.write_fmt(f).unwrap();
 }
 
-pub(crate) fn print_generic_bounds<'a, 'tcx: 'a>(
-    bounds: &'a [clean::GenericBound],
-    cx: &'a Context<'tcx>,
-) -> impl Display + 'a + Captures<'tcx> {
+pub(crate) fn print_generic_bounds(
+    bounds: &[clean::GenericBound],
+    cx: &Context<'_>,
+) -> impl Display {
     fmt::from_fn(move |f| {
         let mut bounds_dup = FxHashSet::default();
 
@@ -57,10 +56,7 @@ pub(crate) fn print_generic_bounds<'a, 'tcx: 'a>(
 }
 
 impl clean::GenericParamDef {
-    pub(crate) fn print<'a, 'tcx: 'a>(
-        &'a self,
-        cx: &'a Context<'tcx>,
-    ) -> impl Display + 'a + Captures<'tcx> {
+    pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
         fmt::from_fn(move |f| match &self.kind {
             clean::GenericParamDefKind::Lifetime { outlives } => {
                 write!(f, "{}", self.name)?;
@@ -80,7 +76,7 @@ impl clean::GenericParamDef {
                     print_generic_bounds(bounds, cx).fmt(f)?;
                 }
 
-                if let Some(ref ty) = default {
+                if let Some(ty) = default {
                     f.write_str(" = ")?;
                     ty.print(cx).fmt(f)?;
                 }
@@ -107,10 +103,7 @@ impl clean::GenericParamDef {
 }
 
 impl clean::Generics {
-    pub(crate) fn print<'a, 'tcx: 'a>(
-        &'a self,
-        cx: &'a Context<'tcx>,
-    ) -> impl Display + 'a + Captures<'tcx> {
+    pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
         fmt::from_fn(move |f| {
             let mut real_params = self.params.iter().filter(|p| !p.is_synthetic_param()).peekable();
             if real_params.peek().is_none() {
@@ -134,10 +127,7 @@ pub(crate) enum Ending {
     NoNewline,
 }
 
-fn print_where_predicate<'a, 'tcx: 'a>(
-    predicate: &'a clean::WherePredicate,
-    cx: &'a Context<'tcx>,
-) -> impl Display + 'a + Captures<'tcx> {
+fn print_where_predicate(predicate: &clean::WherePredicate, cx: &Context<'_>) -> impl Display {
     fmt::from_fn(move |f| {
         match predicate {
             clean::WherePredicate::BoundPredicate { ty, bounds, bound_params } => {
@@ -173,17 +163,17 @@ fn print_where_predicate<'a, 'tcx: 'a>(
 /// * The Generics from which to emit a where-clause.
 /// * The number of spaces to indent each line with.
 /// * Whether the where-clause needs to add a comma and newline after the last bound.
-pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
-    gens: &'a clean::Generics,
-    cx: &'a Context<'tcx>,
+pub(crate) fn print_where_clause(
+    gens: &clean::Generics,
+    cx: &Context<'_>,
     indent: usize,
     ending: Ending,
-) -> impl Display + 'a + Captures<'tcx> {
-    fmt::from_fn(move |f| {
-        if gens.where_predicates.is_empty() {
-            return Ok(());
-        }
+) -> Option<impl Display> {
+    if gens.where_predicates.is_empty() {
+        return None;
+    }
 
+    Some(fmt::from_fn(move |f| {
         let where_preds = fmt::from_fn(|f| {
             gens.where_predicates
                 .iter()
@@ -246,17 +236,17 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
             }
         };
         write!(f, "{clause}")
-    })
+    }))
 }
 
 impl clean::Lifetime {
-    pub(crate) fn print(&self) -> impl Display + '_ {
+    pub(crate) fn print(&self) -> impl Display {
         self.0.as_str()
     }
 }
 
 impl clean::ConstantKind {
-    pub(crate) fn print(&self, tcx: TyCtxt<'_>) -> impl Display + '_ {
+    pub(crate) fn print(&self, tcx: TyCtxt<'_>) -> impl Display {
         let expr = self.expr(tcx);
         fmt::from_fn(move |f| {
             if f.alternate() { f.write_str(&expr) } else { write!(f, "{}", Escape(&expr)) }
@@ -265,7 +255,7 @@ impl clean::ConstantKind {
 }
 
 impl clean::PolyTrait {
-    fn print<'a, 'tcx: 'a>(&'a self, cx: &'a Context<'tcx>) -> impl Display + 'a + Captures<'tcx> {
+    fn print(&self, cx: &Context<'_>) -> impl Display {
         fmt::from_fn(move |f| {
             print_higher_ranked_params_with_space(&self.generic_params, cx, "for").fmt(f)?;
             self.trait_.print(cx).fmt(f)
@@ -274,10 +264,7 @@ impl clean::PolyTrait {
 }
 
 impl clean::GenericBound {
-    pub(crate) fn print<'a, 'tcx: 'a>(
-        &'a self,
-        cx: &'a Context<'tcx>,
-    ) -> impl Display + 'a + Captures<'tcx> {
+    pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
         fmt::from_fn(move |f| match self {
             clean::GenericBound::Outlives(lt) => write!(f, "{}", lt.print()),
             clean::GenericBound::TraitBound(ty, modifiers) => {
@@ -304,7 +291,7 @@ impl clean::GenericBound {
 }
 
 impl clean::GenericArgs {
-    fn print<'a, 'tcx: 'a>(&'a self, cx: &'a Context<'tcx>) -> impl Display + 'a + Captures<'tcx> {
+    fn print(&self, cx: &Context<'_>) -> impl Display {
         fmt::from_fn(move |f| {
             match self {
                 clean::GenericArgs::AngleBracketed { args, constraints } => {
@@ -809,11 +796,11 @@ fn primitive_link_fragment(
     Ok(())
 }
 
-fn tybounds<'a, 'tcx: 'a>(
-    bounds: &'a [clean::PolyTrait],
-    lt: &'a Option<clean::Lifetime>,
-    cx: &'a Context<'tcx>,
-) -> impl Display + 'a + Captures<'tcx> {
+fn tybounds(
+    bounds: &[clean::PolyTrait],
+    lt: &Option<clean::Lifetime>,
+    cx: &Context<'_>,
+) -> impl Display {
     fmt::from_fn(move |f| {
         bounds.iter().map(|bound| bound.print(cx)).joined(" + ", f)?;
         if let Some(lt) = lt {
@@ -825,11 +812,11 @@ fn tybounds<'a, 'tcx: 'a>(
     })
 }
 
-fn print_higher_ranked_params_with_space<'a, 'tcx: 'a>(
-    params: &'a [clean::GenericParamDef],
-    cx: &'a Context<'tcx>,
+fn print_higher_ranked_params_with_space(
+    params: &[clean::GenericParamDef],
+    cx: &Context<'_>,
     keyword: &'static str,
-) -> impl Display + 'a + Captures<'tcx> {
+) -> impl Display {
     fmt::from_fn(move |f| {
         if !params.is_empty() {
             f.write_str(keyword)?;
@@ -841,11 +828,7 @@ fn print_higher_ranked_params_with_space<'a, 'tcx: 'a>(
     })
 }
 
-pub(crate) fn anchor<'a: 'cx, 'cx>(
-    did: DefId,
-    text: Symbol,
-    cx: &'cx Context<'a>,
-) -> impl Display + Captures<'a> + 'cx {
+pub(crate) fn anchor(did: DefId, text: Symbol, cx: &Context<'_>) -> impl Display {
     fmt::from_fn(move |f| {
         let parts = href(did, cx);
         if let Ok((url, short_ty, fqp)) = parts {
@@ -1121,29 +1104,19 @@ fn fmt_type(
 }
 
 impl clean::Type {
-    pub(crate) fn print<'b, 'a: 'b, 'tcx: 'a>(
-        &'a self,
-        cx: &'a Context<'tcx>,
-    ) -> impl Display + 'b + Captures<'tcx> {
+    pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
         fmt::from_fn(move |f| fmt_type(self, f, false, cx))
     }
 }
 
 impl clean::Path {
-    pub(crate) fn print<'b, 'a: 'b, 'tcx: 'a>(
-        &'a self,
-        cx: &'a Context<'tcx>,
-    ) -> impl Display + 'b + Captures<'tcx> {
+    pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
         fmt::from_fn(move |f| resolved_path(f, self.def_id(), self, false, false, cx))
     }
 }
 
 impl clean::Impl {
-    pub(crate) fn print<'a, 'tcx: 'a>(
-        &'a self,
-        use_absolute: bool,
-        cx: &'a Context<'tcx>,
-    ) -> impl Display + 'a + Captures<'tcx> {
+    pub(crate) fn print(&self, use_absolute: bool, cx: &Context<'_>) -> impl Display {
         fmt::from_fn(move |f| {
             f.write_str("impl")?;
             self.generics.print(cx).fmt(f)?;
@@ -1179,15 +1152,15 @@ impl clean::Impl {
                 self.print_type(&self.for_, f, use_absolute, cx)?;
             }
 
-            print_where_clause(&self.generics, cx, 0, Ending::Newline).fmt(f)
+            print_where_clause(&self.generics, cx, 0, Ending::Newline).maybe_display().fmt(f)
         })
     }
-    fn print_type<'a, 'tcx: 'a>(
+    fn print_type(
         &self,
         type_: &clean::Type,
         f: &mut fmt::Formatter<'_>,
         use_absolute: bool,
-        cx: &'a Context<'tcx>,
+        cx: &Context<'_>,
     ) -> Result<(), fmt::Error> {
         if let clean::Type::Tuple(types) = type_
             && let [clean::Type::Generic(name)] = &types[..]
@@ -1258,10 +1231,7 @@ impl clean::Impl {
 }
 
 impl clean::Arguments {
-    pub(crate) fn print<'a, 'tcx: 'a>(
-        &'a self,
-        cx: &'a Context<'tcx>,
-    ) -> impl Display + 'a + Captures<'tcx> {
+    pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
         fmt::from_fn(move |f| {
             self.values
                 .iter()
@@ -1301,10 +1271,7 @@ impl Display for Indent {
 }
 
 impl clean::FnDecl {
-    pub(crate) fn print<'b, 'a: 'b, 'tcx: 'a>(
-        &'a self,
-        cx: &'a Context<'tcx>,
-    ) -> impl Display + 'b + Captures<'tcx> {
+    pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
         fmt::from_fn(move |f| {
             let ellipsis = if self.c_variadic { ", ..." } else { "" };
             if f.alternate() {
@@ -1333,12 +1300,12 @@ impl clean::FnDecl {
     ///   are preserved.
     /// * `indent`: The number of spaces to indent each successive line with, if line-wrapping is
     ///   necessary.
-    pub(crate) fn full_print<'a, 'tcx: 'a>(
-        &'a self,
+    pub(crate) fn full_print(
+        &self,
         header_len: usize,
         indent: usize,
-        cx: &'a Context<'tcx>,
-    ) -> impl Display + 'a + Captures<'tcx> {
+        cx: &Context<'_>,
+    ) -> impl Display {
         fmt::from_fn(move |f| {
             // First, generate the text form of the declaration, with no line wrapping, and count the bytes.
             let mut counter = WriteCounter(0);
@@ -1420,10 +1387,7 @@ impl clean::FnDecl {
         self.print_output(cx).fmt(f)
     }
 
-    fn print_output<'a, 'tcx: 'a>(
-        &'a self,
-        cx: &'a Context<'tcx>,
-    ) -> impl Display + 'a + Captures<'tcx> {
+    fn print_output(&self, cx: &Context<'_>) -> impl Display {
         fmt::from_fn(move |f| match &self.output {
             clean::Tuple(tys) if tys.is_empty() => Ok(()),
             ty if f.alternate() => {
@@ -1434,10 +1398,7 @@ impl clean::FnDecl {
     }
 }
 
-pub(crate) fn visibility_print_with_space<'a, 'tcx: 'a>(
-    item: &clean::Item,
-    cx: &'a Context<'tcx>,
-) -> impl Display + 'a + Captures<'tcx> {
+pub(crate) fn visibility_print_with_space(item: &clean::Item, cx: &Context<'_>) -> impl Display {
     use std::fmt::Write as _;
     let vis: Cow<'static, str> = match item.visibility(cx.tcx()) {
         None => "".into(),
@@ -1546,10 +1507,7 @@ pub(crate) fn print_constness_with_space(
 }
 
 impl clean::Import {
-    pub(crate) fn print<'a, 'tcx: 'a>(
-        &'a self,
-        cx: &'a Context<'tcx>,
-    ) -> impl Display + 'a + Captures<'tcx> {
+    pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
         fmt::from_fn(move |f| match self.kind {
             clean::ImportKind::Simple(name) => {
                 if name == self.source.path.last() {
@@ -1570,10 +1528,7 @@ impl clean::Import {
 }
 
 impl clean::ImportSource {
-    pub(crate) fn print<'a, 'tcx: 'a>(
-        &'a self,
-        cx: &'a Context<'tcx>,
-    ) -> impl Display + 'a + Captures<'tcx> {
+    pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
         fmt::from_fn(move |f| match self.did {
             Some(did) => resolved_path(f, did, &self.path, true, false, cx),
             _ => {
@@ -1593,10 +1548,7 @@ impl clean::ImportSource {
 }
 
 impl clean::AssocItemConstraint {
-    pub(crate) fn print<'a, 'tcx: 'a>(
-        &'a self,
-        cx: &'a Context<'tcx>,
-    ) -> impl Display + 'a + Captures<'tcx> {
+    pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
         fmt::from_fn(move |f| {
             f.write_str(self.assoc.name.as_str())?;
             self.assoc.args.print(cx).fmt(f)?;
@@ -1627,15 +1579,12 @@ pub(crate) fn print_abi_with_space(abi: ExternAbi) -> impl Display {
     })
 }
 
-pub(crate) fn print_default_space<'a>(v: bool) -> &'a str {
+pub(crate) fn print_default_space(v: bool) -> &'static str {
     if v { "default " } else { "" }
 }
 
 impl clean::GenericArg {
-    pub(crate) fn print<'a, 'tcx: 'a>(
-        &'a self,
-        cx: &'a Context<'tcx>,
-    ) -> impl Display + 'a + Captures<'tcx> {
+    pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
         fmt::from_fn(move |f| match self {
             clean::GenericArg::Lifetime(lt) => lt.print().fmt(f),
             clean::GenericArg::Type(ty) => ty.print(cx).fmt(f),
@@ -1646,10 +1595,7 @@ impl clean::GenericArg {
 }
 
 impl clean::Term {
-    pub(crate) fn print<'a, 'tcx: 'a>(
-        &'a self,
-        cx: &'a Context<'tcx>,
-    ) -> impl Display + 'a + Captures<'tcx> {
+    pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
         fmt::from_fn(move |f| match self {
             clean::Term::Type(ty) => ty.print(cx).fmt(f),
             clean::Term::Constant(ct) => ct.print(cx.tcx()).fmt(f),
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 146bdd34069..5f69e79f3ab 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -237,8 +237,7 @@ impl<'tcx> Context<'tcx> {
         };
 
         if !render_redirect_pages {
-            let mut page_buffer = String::new();
-            print_item(self, it, &mut page_buffer);
+            let content = print_item(self, it);
             let page = layout::Page {
                 css_class: tyname_s,
                 root_path: &self.root_path(),
@@ -254,7 +253,7 @@ impl<'tcx> Context<'tcx> {
                 BufDisplay(|buf: &mut String| {
                     print_sidebar(self, it, buf);
                 }),
-                page_buffer,
+                content,
                 &self.shared.style_files,
             )
         } else {
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 204631063a2..b2ad2fa773a 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -38,7 +38,7 @@ mod type_layout;
 mod write_shared;
 
 use std::collections::VecDeque;
-use std::fmt::{self, Write};
+use std::fmt::{self, Display as _, Write};
 use std::iter::Peekable;
 use std::path::PathBuf;
 use std::{fs, str};
@@ -47,7 +47,6 @@ use rinja::Template;
 use rustc_attr_parsing::{
     ConstStability, DeprecatedSince, Deprecation, RustcVersion, StabilityLevel, StableSince,
 };
-use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_hir::Mutability;
 use rustc_hir::def_id::{DefId, DefIdSet};
@@ -82,7 +81,7 @@ use crate::html::{highlight, sources};
 use crate::scrape_examples::{CallData, CallLocation};
 use crate::{DOC_RUST_LANG_ORG_VERSION, try_none};
 
-pub(crate) fn ensure_trailing_slash(v: &str) -> impl fmt::Display + '_ {
+pub(crate) fn ensure_trailing_slash(v: &str) -> impl fmt::Display {
     fmt::from_fn(move |f| {
         if !v.ends_with('/') && !v.is_empty() { write!(f, "{v}/") } else { f.write_str(v) }
     })
@@ -310,7 +309,7 @@ impl ItemEntry {
 }
 
 impl ItemEntry {
-    pub(crate) fn print(&self) -> impl fmt::Display + '_ {
+    pub(crate) fn print(&self) -> impl fmt::Display {
         fmt::from_fn(move |f| write!(f, "<a href=\"{}\">{}</a>", self.url, Escape(&self.name)))
     }
 }
@@ -505,12 +504,12 @@ fn scrape_examples_help(shared: &SharedContext<'_>) -> String {
     )
 }
 
-fn document<'a, 'cx: 'a>(
-    cx: &'a Context<'cx>,
-    item: &'a clean::Item,
-    parent: Option<&'a clean::Item>,
+fn document(
+    cx: &Context<'_>,
+    item: &clean::Item,
+    parent: Option<&clean::Item>,
     heading_offset: HeadingOffset,
-) -> impl fmt::Display + 'a + Captures<'cx> {
+) -> impl fmt::Display {
     if let Some(ref name) = item.name {
         info!("Documenting {name}");
     }
@@ -526,12 +525,12 @@ fn document<'a, 'cx: 'a>(
 }
 
 /// Render md_text as markdown.
-fn render_markdown<'a, 'cx: 'a>(
-    cx: &'a Context<'cx>,
-    md_text: &'a str,
+fn render_markdown(
+    cx: &Context<'_>,
+    md_text: &str,
     links: Vec<RenderedLink>,
     heading_offset: HeadingOffset,
-) -> impl fmt::Display + 'a + Captures<'cx> {
+) -> impl fmt::Display {
     fmt::from_fn(move |f| {
         write!(
             f,
@@ -552,13 +551,13 @@ fn render_markdown<'a, 'cx: 'a>(
 
 /// Writes a documentation block containing only the first paragraph of the documentation. If the
 /// docs are longer, a "Read more" link is appended to the end.
-fn document_short<'a, 'cx: 'a>(
-    item: &'a clean::Item,
-    cx: &'a Context<'cx>,
-    link: AssocItemLink<'a>,
-    parent: &'a clean::Item,
+fn document_short(
+    item: &clean::Item,
+    cx: &Context<'_>,
+    link: AssocItemLink<'_>,
+    parent: &clean::Item,
     show_def_docs: bool,
-) -> impl fmt::Display + 'a + Captures<'cx> {
+) -> impl fmt::Display {
     fmt::from_fn(move |f| {
         document_item_info(cx, item, Some(parent)).render_into(f).unwrap();
         if !show_def_docs {
@@ -595,28 +594,28 @@ fn document_short<'a, 'cx: 'a>(
     })
 }
 
-fn document_full_collapsible<'a, 'cx: 'a>(
-    item: &'a clean::Item,
-    cx: &'a Context<'cx>,
+fn document_full_collapsible(
+    item: &clean::Item,
+    cx: &Context<'_>,
     heading_offset: HeadingOffset,
-) -> impl fmt::Display + 'a + Captures<'cx> {
+) -> impl fmt::Display {
     document_full_inner(item, cx, true, heading_offset)
 }
 
-fn document_full<'a, 'cx: 'a>(
-    item: &'a clean::Item,
-    cx: &'a Context<'cx>,
+fn document_full(
+    item: &clean::Item,
+    cx: &Context<'_>,
     heading_offset: HeadingOffset,
-) -> impl fmt::Display + 'a + Captures<'cx> {
+) -> impl fmt::Display {
     document_full_inner(item, cx, false, heading_offset)
 }
 
-fn document_full_inner<'a, 'cx: 'a>(
-    item: &'a clean::Item,
-    cx: &'a Context<'cx>,
+fn document_full_inner(
+    item: &clean::Item,
+    cx: &Context<'_>,
     is_collapsible: bool,
     heading_offset: HeadingOffset,
-) -> impl fmt::Display + 'a + Captures<'cx> {
+) -> impl fmt::Display {
     fmt::from_fn(move |f| {
         if let Some(s) = item.opt_doc_value() {
             debug!("Doc block: =====\n{s}\n=====");
@@ -774,9 +773,7 @@ pub(crate) fn render_impls(
             let did = i.trait_did().unwrap();
             let provided_trait_methods = i.inner_impl().provided_trait_methods(cx.tcx());
             let assoc_link = AssocItemLink::GotoSource(did.into(), &provided_trait_methods);
-            let mut buffer = String::new();
-            render_impl(
-                &mut buffer,
+            let imp = render_impl(
                 cx,
                 i,
                 containing_item,
@@ -791,7 +788,7 @@ pub(crate) fn render_impls(
                     toggle_open_by_default,
                 },
             );
-            buffer
+            imp.to_string()
         })
         .collect::<Vec<_>>();
     rendered_impls.sort();
@@ -799,11 +796,11 @@ pub(crate) fn render_impls(
 }
 
 /// Build a (possibly empty) `href` attribute (a key-value pair) for the given associated item.
-fn assoc_href_attr<'a, 'tcx>(
+fn assoc_href_attr(
     it: &clean::Item,
-    link: AssocItemLink<'a>,
-    cx: &Context<'tcx>,
-) -> Option<impl fmt::Display + 'a + Captures<'tcx>> {
+    link: AssocItemLink<'_>,
+    cx: &Context<'_>,
+) -> Option<impl fmt::Display> {
     let name = it.name.unwrap();
     let item_type = it.type_();
 
@@ -814,7 +811,7 @@ fn assoc_href_attr<'a, 'tcx>(
     }
 
     let href = match link {
-        AssocItemLink::Anchor(Some(ref id)) => Href::AnchorId(id),
+        AssocItemLink::Anchor(Some(id)) => Href::AnchorId(id),
         AssocItemLink::Anchor(None) => Href::Anchor(item_type),
         AssocItemLink::GotoSource(did, provided_methods) => {
             // We're creating a link from the implementation of an associated item to its
@@ -880,7 +877,6 @@ enum AssocConstValue<'a> {
 }
 
 fn assoc_const(
-    w: &mut String,
     it: &clean::Item,
     generics: &clean::Generics,
     ty: &clean::Type,
@@ -888,11 +884,11 @@ fn assoc_const(
     link: AssocItemLink<'_>,
     indent: usize,
     cx: &Context<'_>,
-) {
+) -> impl fmt::Display {
     let tcx = cx.tcx();
-    write_str(
-        w,
-        format_args!(
+    fmt::from_fn(move |w| {
+        write!(
+            w,
             "{indent}{vis}const <a{href} class=\"constant\">{name}</a>{generics}: {ty}",
             indent = " ".repeat(indent),
             vis = visibility_print_with_space(it, cx),
@@ -900,28 +896,27 @@ fn assoc_const(
             name = it.name.as_ref().unwrap(),
             generics = generics.print(cx),
             ty = ty.print(cx),
-        ),
-    );
-    if let AssocConstValue::TraitDefault(konst) | AssocConstValue::Impl(konst) = value {
-        // FIXME: `.value()` uses `clean::utils::format_integer_with_underscore_sep` under the
-        //        hood which adds noisy underscores and a type suffix to number literals.
-        //        This hurts readability in this context especially when more complex expressions
-        //        are involved and it doesn't add much of value.
-        //        Find a way to print constants here without all that jazz.
-        let repr = konst.value(tcx).unwrap_or_else(|| konst.expr(tcx));
-        if match value {
-            AssocConstValue::TraitDefault(_) => true, // always show
-            AssocConstValue::Impl(_) => repr != "_",  // show if there is a meaningful value to show
-            AssocConstValue::None => unreachable!(),
-        } {
-            write_str(w, format_args!(" = {}", Escape(&repr)));
+        )?;
+        if let AssocConstValue::TraitDefault(konst) | AssocConstValue::Impl(konst) = value {
+            // FIXME: `.value()` uses `clean::utils::format_integer_with_underscore_sep` under the
+            //        hood which adds noisy underscores and a type suffix to number literals.
+            //        This hurts readability in this context especially when more complex expressions
+            //        are involved and it doesn't add much of value.
+            //        Find a way to print constants here without all that jazz.
+            let repr = konst.value(tcx).unwrap_or_else(|| konst.expr(tcx));
+            if match value {
+                AssocConstValue::TraitDefault(_) => true, // always show
+                AssocConstValue::Impl(_) => repr != "_", // show if there is a meaningful value to show
+                AssocConstValue::None => unreachable!(),
+            } {
+                write!(w, " = {}", Escape(&repr))?;
+            }
         }
-    }
-    write_str(w, format_args!("{}", print_where_clause(generics, cx, indent, Ending::NoNewline)));
+        write!(w, "{}", print_where_clause(generics, cx, indent, Ending::NoNewline).maybe_display())
+    })
 }
 
 fn assoc_type(
-    w: &mut String,
     it: &clean::Item,
     generics: &clean::Generics,
     bounds: &[clean::GenericBound],
@@ -929,30 +924,29 @@ fn assoc_type(
     link: AssocItemLink<'_>,
     indent: usize,
     cx: &Context<'_>,
-) {
-    write_str(
-        w,
-        format_args!(
+) -> impl fmt::Display {
+    fmt::from_fn(move |w| {
+        write!(
+            w,
             "{indent}{vis}type <a{href} class=\"associatedtype\">{name}</a>{generics}",
             indent = " ".repeat(indent),
             vis = visibility_print_with_space(it, cx),
             href = assoc_href_attr(it, link, cx).maybe_display(),
             name = it.name.as_ref().unwrap(),
             generics = generics.print(cx),
-        ),
-    );
-    if !bounds.is_empty() {
-        write_str(w, format_args!(": {}", print_generic_bounds(bounds, cx)));
-    }
-    // Render the default before the where-clause which aligns with the new recommended style. See #89122.
-    if let Some(default) = default {
-        write_str(w, format_args!(" = {}", default.print(cx)));
-    }
-    write_str(w, format_args!("{}", print_where_clause(generics, cx, indent, Ending::NoNewline)));
+        )?;
+        if !bounds.is_empty() {
+            write!(w, ": {}", print_generic_bounds(bounds, cx))?;
+        }
+        // Render the default before the where-clause which aligns with the new recommended style. See #89122.
+        if let Some(default) = default {
+            write!(w, " = {}", default.print(cx))?;
+        }
+        write!(w, "{}", print_where_clause(generics, cx, indent, Ending::NoNewline).maybe_display())
+    })
 }
 
 fn assoc_method(
-    w: &mut String,
     meth: &clean::Item,
     g: &clean::Generics,
     d: &clean::FnDecl,
@@ -960,7 +954,7 @@ fn assoc_method(
     parent: ItemType,
     cx: &Context<'_>,
     render_mode: RenderMode,
-) {
+) -> impl fmt::Display {
     let tcx = cx.tcx();
     let header = meth.fn_header(tcx).expect("Trying to get header from a non-function item");
     let name = meth.name.as_ref().unwrap();
@@ -976,61 +970,53 @@ fn assoc_method(
         ),
         RenderMode::ForDeref { .. } => "",
     };
-    let asyncness = header.asyncness.print_with_space();
-    let safety = header.safety.print_with_space();
-    let abi = print_abi_with_space(header.abi).to_string();
-    let href = assoc_href_attr(meth, link, cx).maybe_display();
-
-    // NOTE: `{:#}` does not print HTML formatting, `{}` does. So `g.print` can't be reused between the length calculation and `write!`.
-    let generics_len = format!("{:#}", g.print(cx)).len();
-    let mut header_len = "fn ".len()
-        + vis.len()
-        + defaultness.len()
-        + constness.len()
-        + asyncness.len()
-        + safety.len()
-        + abi.len()
-        + name.as_str().len()
-        + generics_len;
-
-    let notable_traits = notable_traits_button(&d.output, cx).maybe_display();
-
-    let (indent, indent_str, end_newline) = if parent == ItemType::Trait {
-        header_len += 4;
-        let indent_str = "    ";
-        write_str(w, format_args!("{}", render_attributes_in_pre(meth, indent_str, cx)));
-        (4, indent_str, Ending::NoNewline)
-    } else {
-        render_attributes_in_code(w, meth, cx);
-        (0, "", Ending::Newline)
-    };
-    w.reserve(header_len + "<a href=\"\" class=\"fn\">{".len() + "</a>".len());
-    write_str(
-        w,
-        format_args!(
+
+    fmt::from_fn(move |w| {
+        let asyncness = header.asyncness.print_with_space();
+        let safety = header.safety.print_with_space();
+        let abi = print_abi_with_space(header.abi).to_string();
+        let href = assoc_href_attr(meth, link, cx).maybe_display();
+
+        // NOTE: `{:#}` does not print HTML formatting, `{}` does. So `g.print` can't be reused between the length calculation and `write!`.
+        let generics_len = format!("{:#}", g.print(cx)).len();
+        let mut header_len = "fn ".len()
+            + vis.len()
+            + defaultness.len()
+            + constness.len()
+            + asyncness.len()
+            + safety.len()
+            + abi.len()
+            + name.as_str().len()
+            + generics_len;
+
+        let notable_traits = notable_traits_button(&d.output, cx).maybe_display();
+
+        let (indent, indent_str, end_newline) = if parent == ItemType::Trait {
+            header_len += 4;
+            let indent_str = "    ";
+            write!(w, "{}", render_attributes_in_pre(meth, indent_str, cx))?;
+            (4, indent_str, Ending::NoNewline)
+        } else {
+            render_attributes_in_code(w, meth, cx);
+            (0, "", Ending::Newline)
+        };
+        write!(
+            w,
             "{indent}{vis}{defaultness}{constness}{asyncness}{safety}{abi}fn \
-         <a{href} class=\"fn\">{name}</a>{generics}{decl}{notable_traits}{where_clause}",
+            <a{href} class=\"fn\">{name}</a>{generics}{decl}{notable_traits}{where_clause}",
             indent = indent_str,
-            vis = vis,
-            defaultness = defaultness,
-            constness = constness,
-            asyncness = asyncness,
-            safety = safety,
-            abi = abi,
-            href = href,
-            name = name,
             generics = g.print(cx),
             decl = d.full_print(header_len, indent, cx),
-            where_clause = print_where_clause(g, cx, indent, end_newline),
-        ),
-    );
+            where_clause = print_where_clause(g, cx, indent, end_newline).maybe_display(),
+        )
+    })
 }
 
 /// Writes a span containing the versions at which an item became stable and/or const-stable. For
 /// example, if the item became stable at 1.0.0, and const-stable at 1.45.0, this function would
 /// write a span containing "1.0.0 (const: 1.45.0)".
 ///
-/// Returns `true` if a stability annotation was rendered.
+/// Returns `None` if there is no stability annotation to be rendered.
 ///
 /// Stability and const-stability are considered separately. If the item is unstable, no version
 /// will be written. If the item is const-unstable, "const: unstable" will be appended to the
@@ -1041,11 +1027,10 @@ fn assoc_method(
 /// will include the const-stable version, but no stable version will be emitted, as a natural
 /// consequence of the above rules.
 fn render_stability_since_raw_with_extra(
-    w: &mut String,
     stable_version: Option<StableSince>,
     const_stability: Option<ConstStability>,
     extra_class: &str,
-) -> bool {
+) -> Option<impl fmt::Display> {
     let mut title = String::new();
     let mut stability = String::new();
 
@@ -1095,14 +1080,9 @@ fn render_stability_since_raw_with_extra(
         }
     }
 
-    if !stability.is_empty() {
-        write_str(
-            w,
-            format_args!(r#"<span class="since{extra_class}" title="{title}">{stability}</span>"#),
-        );
-    }
-
-    !stability.is_empty()
+    (!stability.is_empty()).then_some(fmt::from_fn(move |w| {
+        write!(w, r#"<span class="since{extra_class}" title="{title}">{stability}</span>"#)
+    }))
 }
 
 fn since_to_string(since: &StableSince) -> Option<String> {
@@ -1115,31 +1095,25 @@ fn since_to_string(since: &StableSince) -> Option<String> {
 
 #[inline]
 fn render_stability_since_raw(
-    w: &mut String,
     ver: Option<StableSince>,
     const_stability: Option<ConstStability>,
-) -> bool {
-    render_stability_since_raw_with_extra(w, ver, const_stability, "")
+) -> Option<impl fmt::Display> {
+    render_stability_since_raw_with_extra(ver, const_stability, "")
 }
 
 fn render_assoc_item(
-    w: &mut String,
     item: &clean::Item,
     link: AssocItemLink<'_>,
     parent: ItemType,
     cx: &Context<'_>,
     render_mode: RenderMode,
-) {
-    match &item.kind {
-        clean::StrippedItem(..) => {}
-        clean::RequiredMethodItem(m) => {
-            assoc_method(w, item, &m.generics, &m.decl, link, parent, cx, render_mode)
-        }
-        clean::MethodItem(m, _) => {
-            assoc_method(w, item, &m.generics, &m.decl, link, parent, cx, render_mode)
+) -> impl fmt::Display {
+    fmt::from_fn(move |f| match &item.kind {
+        clean::StrippedItem(..) => Ok(()),
+        clean::RequiredMethodItem(m) | clean::MethodItem(m, _) => {
+            assoc_method(item, &m.generics, &m.decl, link, parent, cx, render_mode).fmt(f)
         }
         clean::RequiredAssocConstItem(generics, ty) => assoc_const(
-            w,
             item,
             generics,
             ty,
@@ -1147,9 +1121,9 @@ fn render_assoc_item(
             link,
             if parent == ItemType::Trait { 4 } else { 0 },
             cx,
-        ),
+        )
+        .fmt(f),
         clean::ProvidedAssocConstItem(ci) => assoc_const(
-            w,
             item,
             &ci.generics,
             &ci.type_,
@@ -1157,9 +1131,9 @@ fn render_assoc_item(
             link,
             if parent == ItemType::Trait { 4 } else { 0 },
             cx,
-        ),
+        )
+        .fmt(f),
         clean::ImplAssocConstItem(ci) => assoc_const(
-            w,
             item,
             &ci.generics,
             &ci.type_,
@@ -1167,9 +1141,9 @@ fn render_assoc_item(
             link,
             if parent == ItemType::Trait { 4 } else { 0 },
             cx,
-        ),
-        clean::RequiredAssocTypeItem(ref generics, ref bounds) => assoc_type(
-            w,
+        )
+        .fmt(f),
+        clean::RequiredAssocTypeItem(generics, bounds) => assoc_type(
             item,
             generics,
             bounds,
@@ -1177,9 +1151,9 @@ fn render_assoc_item(
             link,
             if parent == ItemType::Trait { 4 } else { 0 },
             cx,
-        ),
-        clean::AssocTypeItem(ref ty, ref bounds) => assoc_type(
-            w,
+        )
+        .fmt(f),
+        clean::AssocTypeItem(ty, bounds) => assoc_type(
             item,
             &ty.generics,
             bounds,
@@ -1187,18 +1161,15 @@ fn render_assoc_item(
             link,
             if parent == ItemType::Trait { 4 } else { 0 },
             cx,
-        ),
+        )
+        .fmt(f),
         _ => panic!("render_assoc_item called on non-associated-item"),
-    }
+    })
 }
 
 // When an attribute is rendered inside a `<pre>` tag, it is formatted using
 // a whitespace prefix and newline.
-fn render_attributes_in_pre<'a, 'tcx: 'a>(
-    it: &'a clean::Item,
-    prefix: &'a str,
-    cx: &'a Context<'tcx>,
-) -> impl fmt::Display + Captures<'a> + Captures<'tcx> {
+fn render_attributes_in_pre(it: &clean::Item, prefix: &str, cx: &Context<'_>) -> impl fmt::Display {
     fmt::from_fn(move |f| {
         for a in it.attributes(cx.tcx(), cx.cache(), false) {
             writeln!(f, "{prefix}{a}")?;
@@ -1231,28 +1202,28 @@ impl<'a> AssocItemLink<'a> {
 }
 
 pub fn write_section_heading(
-    w: &mut impl fmt::Write,
     title: &str,
     id: &str,
     extra_class: Option<&str>,
     extra: impl fmt::Display,
-) {
-    let (extra_class, whitespace) = match extra_class {
-        Some(extra) => (extra, " "),
-        None => ("", ""),
-    };
-    write!(
-        w,
-        "<h2 id=\"{id}\" class=\"{extra_class}{whitespace}section-header\">\
+) -> impl fmt::Display {
+    fmt::from_fn(move |w| {
+        let (extra_class, whitespace) = match extra_class {
+            Some(extra) => (extra, " "),
+            None => ("", ""),
+        };
+        write!(
+            w,
+            "<h2 id=\"{id}\" class=\"{extra_class}{whitespace}section-header\">\
             {title}\
             <a href=\"#{id}\" class=\"anchor\">§</a>\
          </h2>{extra}",
-    )
-    .unwrap();
+        )
+    })
 }
 
-fn write_impl_section_heading(w: &mut impl fmt::Write, title: &str, id: &str) {
-    write_section_heading(w, title, id, None, "")
+fn write_impl_section_heading(title: &str, id: &str) -> impl fmt::Display {
+    write_section_heading(title, id, None, "")
 }
 
 pub(crate) fn render_all_impls(
@@ -1269,35 +1240,43 @@ pub(crate) fn render_all_impls(
         buf
     };
     if !impls.is_empty() {
-        write_impl_section_heading(&mut w, "Trait Implementations", "trait-implementations");
-        write!(w, "<div id=\"trait-implementations-list\">{impls}</div>").unwrap();
+        write!(
+            w,
+            "{}<div id=\"trait-implementations-list\">{impls}</div>",
+            write_impl_section_heading("Trait Implementations", "trait-implementations")
+        )
+        .unwrap();
     }
 
     if !synthetic.is_empty() {
-        write_impl_section_heading(
-            &mut w,
-            "Auto Trait Implementations",
-            "synthetic-implementations",
-        );
-        w.write_str("<div id=\"synthetic-implementations-list\">").unwrap();
+        write!(
+            w,
+            "{}<div id=\"synthetic-implementations-list\">",
+            write_impl_section_heading("Auto Trait Implementations", "synthetic-implementations",)
+        )
+        .unwrap();
         render_impls(cx, &mut w, synthetic, containing_item, false);
         w.write_str("</div>").unwrap();
     }
 
     if !blanket_impl.is_empty() {
-        write_impl_section_heading(&mut w, "Blanket Implementations", "blanket-implementations");
-        w.write_str("<div id=\"blanket-implementations-list\">").unwrap();
+        write!(
+            w,
+            "{}<div id=\"blanket-implementations-list\">",
+            write_impl_section_heading("Blanket Implementations", "blanket-implementations")
+        )
+        .unwrap();
         render_impls(cx, &mut w, blanket_impl, containing_item, false);
         w.write_str("</div>").unwrap();
     }
 }
 
-fn render_assoc_items<'a, 'cx: 'a>(
-    cx: &'a Context<'cx>,
-    containing_item: &'a clean::Item,
+fn render_assoc_items(
+    cx: &Context<'_>,
+    containing_item: &clean::Item,
     it: DefId,
-    what: AssocItemRender<'a>,
-) -> impl fmt::Display + 'a + Captures<'cx> {
+    what: AssocItemRender<'_>,
+) -> impl fmt::Display {
     fmt::from_fn(move |f| {
         let mut derefs = DefIdSet::default();
         derefs.insert(it);
@@ -1323,25 +1302,34 @@ fn render_assoc_items_inner(
         let mut tmp_buf = String::new();
         let (render_mode, id, class_html) = match what {
             AssocItemRender::All => {
-                write_impl_section_heading(&mut tmp_buf, "Implementations", "implementations");
+                write_str(
+                    &mut tmp_buf,
+                    format_args!(
+                        "{}",
+                        write_impl_section_heading("Implementations", "implementations")
+                    ),
+                );
                 (RenderMode::Normal, "implementations-list".to_owned(), "")
             }
             AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => {
                 let id =
                     cx.derive_id(small_url_encode(format!("deref-methods-{:#}", type_.print(cx))));
                 let derived_id = cx.derive_id(&id);
-                tmp_buf.push_str("<details class=\"toggle big-toggle\" open><summary>");
                 close_tags.push("</details>");
-                write_impl_section_heading(
+                write_str(
                     &mut tmp_buf,
-                    &format!(
-                        "<span>Methods from {trait_}&lt;Target = {type_}&gt;</span>",
-                        trait_ = trait_.print(cx),
-                        type_ = type_.print(cx),
+                    format_args!(
+                        "<details class=\"toggle big-toggle\" open><summary>{}</summary>",
+                        write_impl_section_heading(
+                            &format!(
+                                "<span>Methods from {trait_}&lt;Target = {type_}&gt;</span>",
+                                trait_ = trait_.print(cx),
+                                type_ = type_.print(cx),
+                            ),
+                            &id,
+                        )
                     ),
-                    &id,
                 );
-                tmp_buf.push_str("</summary>");
                 if let Some(def_id) = type_.def_id(cx.cache()) {
                     cx.deref_id_map.borrow_mut().insert(def_id, id);
                 }
@@ -1350,21 +1338,26 @@ fn render_assoc_items_inner(
         };
         let mut impls_buf = String::new();
         for i in &non_trait {
-            render_impl(
+            write_str(
                 &mut impls_buf,
-                cx,
-                i,
-                containing_item,
-                AssocItemLink::Anchor(None),
-                render_mode,
-                None,
-                &[],
-                ImplRenderingParameters {
-                    show_def_docs: true,
-                    show_default_items: true,
-                    show_non_assoc_items: true,
-                    toggle_open_by_default: true,
-                },
+                format_args!(
+                    "{}",
+                    render_impl(
+                        cx,
+                        i,
+                        containing_item,
+                        AssocItemLink::Anchor(None),
+                        render_mode,
+                        None,
+                        &[],
+                        ImplRenderingParameters {
+                            show_def_docs: true,
+                            show_default_items: true,
+                            show_non_assoc_items: true,
+                            toggle_open_by_default: true,
+                        },
+                    )
+                ),
             );
         }
         if !impls_buf.is_empty() {
@@ -1468,10 +1461,10 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) ->
     }
 }
 
-pub(crate) fn notable_traits_button<'a, 'tcx>(
-    ty: &'a clean::Type,
-    cx: &'a Context<'tcx>,
-) -> Option<impl fmt::Display + 'a + Captures<'tcx>> {
+pub(crate) fn notable_traits_button(
+    ty: &clean::Type,
+    cx: &Context<'_>,
+) -> Option<impl fmt::Display> {
     let mut has_notable_trait = false;
 
     if ty.is_unit() {
@@ -1564,20 +1557,23 @@ fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) {
                 );
                 for it in &impl_.items {
                     if let clean::AssocTypeItem(ref tydef, ref _bounds) = it.kind {
-                        out.push_str("<div class=\"where\">    ");
                         let empty_set = FxIndexSet::default();
                         let src_link = AssocItemLink::GotoSource(trait_did.into(), &empty_set);
-                        assoc_type(
+                        write_str(
                             &mut out,
-                            it,
-                            &tydef.generics,
-                            &[], // intentionally leaving out bounds
-                            Some(&tydef.type_),
-                            src_link,
-                            0,
-                            cx,
+                            format_args!(
+                                "<div class=\"where\">    {};</div>",
+                                assoc_type(
+                                    it,
+                                    &tydef.generics,
+                                    &[], // intentionally leaving out bounds
+                                    Some(&tydef.type_),
+                                    src_link,
+                                    0,
+                                    cx,
+                                )
+                            ),
                         );
-                        out.push_str(";</div>");
                     }
                 }
             }
@@ -1623,7 +1619,6 @@ struct ImplRenderingParameters {
 }
 
 fn render_impl(
-    w: &mut String,
     cx: &Context<'_>,
     i: &Impl,
     parent: &clean::Item,
@@ -1632,513 +1627,549 @@ fn render_impl(
     use_absolute: Option<bool>,
     aliases: &[String],
     rendering_params: ImplRenderingParameters,
-) {
-    let cache = &cx.shared.cache;
-    let traits = &cache.traits;
-    let trait_ = i.trait_did().map(|did| &traits[&did]);
-    let mut close_tags = <Vec<&str>>::with_capacity(2);
-
-    // For trait implementations, the `interesting` output contains all methods that have doc
-    // comments, and the `boring` output contains all methods that do not. The distinction is
-    // used to allow hiding the boring methods.
-    // `containing_item` is used for rendering stability info. If the parent is a trait impl,
-    // `containing_item` will the grandparent, since trait impls can't have stability attached.
-    fn doc_impl_item(
-        boring: &mut String,
-        interesting: &mut String,
-        cx: &Context<'_>,
-        item: &clean::Item,
-        parent: &clean::Item,
-        link: AssocItemLink<'_>,
-        render_mode: RenderMode,
-        is_default_item: bool,
-        trait_: Option<&clean::Trait>,
-        rendering_params: ImplRenderingParameters,
-    ) {
-        let item_type = item.type_();
-        let name = item.name.as_ref().unwrap();
-
-        let render_method_item = rendering_params.show_non_assoc_items
-            && match render_mode {
-                RenderMode::Normal => true,
-                RenderMode::ForDeref { mut_: deref_mut_ } => {
-                    should_render_item(item, deref_mut_, cx.tcx())
-                }
-            };
+) -> impl fmt::Display {
+    fmt::from_fn(move |w| {
+        let cache = &cx.shared.cache;
+        let traits = &cache.traits;
+        let trait_ = i.trait_did().map(|did| &traits[&did]);
+        let mut close_tags = <Vec<&str>>::with_capacity(2);
+
+        // For trait implementations, the `interesting` output contains all methods that have doc
+        // comments, and the `boring` output contains all methods that do not. The distinction is
+        // used to allow hiding the boring methods.
+        // `containing_item` is used for rendering stability info. If the parent is a trait impl,
+        // `containing_item` will the grandparent, since trait impls can't have stability attached.
+        fn doc_impl_item(
+            boring: &mut String,
+            interesting: &mut String,
+            cx: &Context<'_>,
+            item: &clean::Item,
+            parent: &clean::Item,
+            link: AssocItemLink<'_>,
+            render_mode: RenderMode,
+            is_default_item: bool,
+            trait_: Option<&clean::Trait>,
+            rendering_params: ImplRenderingParameters,
+        ) {
+            let item_type = item.type_();
+            let name = item.name.as_ref().unwrap();
+
+            let render_method_item = rendering_params.show_non_assoc_items
+                && match render_mode {
+                    RenderMode::Normal => true,
+                    RenderMode::ForDeref { mut_: deref_mut_ } => {
+                        should_render_item(item, deref_mut_, cx.tcx())
+                    }
+                };
 
-        let in_trait_class = if trait_.is_some() { " trait-impl" } else { "" };
-
-        let mut doc_buffer = String::new();
-        let mut info_buffer = String::new();
-        let mut short_documented = true;
-
-        if render_method_item {
-            if !is_default_item {
-                if let Some(t) = trait_ {
-                    // The trait item may have been stripped so we might not
-                    // find any documentation or stability for it.
-                    if let Some(it) = t.items.iter().find(|i| i.name == item.name) {
-                        // We need the stability of the item from the trait
-                        // because impls can't have a stability.
-                        if !item.doc_value().is_empty() {
-                            document_item_info(cx, it, Some(parent))
-                                .render_into(&mut info_buffer)
-                                .unwrap();
+            let in_trait_class = if trait_.is_some() { " trait-impl" } else { "" };
+
+            let mut doc_buffer = String::new();
+            let mut info_buffer = String::new();
+            let mut short_documented = true;
+
+            if render_method_item {
+                if !is_default_item {
+                    if let Some(t) = trait_ {
+                        // The trait item may have been stripped so we might not
+                        // find any documentation or stability for it.
+                        if let Some(it) = t.items.iter().find(|i| i.name == item.name) {
+                            // We need the stability of the item from the trait
+                            // because impls can't have a stability.
+                            if !item.doc_value().is_empty() {
+                                document_item_info(cx, it, Some(parent))
+                                    .render_into(&mut info_buffer)
+                                    .unwrap();
+                                write_str(
+                                    &mut doc_buffer,
+                                    format_args!("{}", document_full(item, cx, HeadingOffset::H5)),
+                                );
+                                short_documented = false;
+                            } else {
+                                // In case the item isn't documented,
+                                // provide short documentation from the trait.
+                                write_str(
+                                    &mut doc_buffer,
+                                    format_args!(
+                                        "{}",
+                                        document_short(
+                                            it,
+                                            cx,
+                                            link,
+                                            parent,
+                                            rendering_params.show_def_docs,
+                                        )
+                                    ),
+                                );
+                            }
+                        }
+                    } else {
+                        document_item_info(cx, item, Some(parent))
+                            .render_into(&mut info_buffer)
+                            .unwrap();
+                        if rendering_params.show_def_docs {
                             write_str(
                                 &mut doc_buffer,
                                 format_args!("{}", document_full(item, cx, HeadingOffset::H5)),
                             );
                             short_documented = false;
-                        } else {
-                            // In case the item isn't documented,
-                            // provide short documentation from the trait.
-                            write_str(
-                                &mut doc_buffer,
-                                format_args!(
-                                    "{}",
-                                    document_short(
-                                        it,
-                                        cx,
-                                        link,
-                                        parent,
-                                        rendering_params.show_def_docs,
-                                    )
-                                ),
-                            );
                         }
                     }
                 } else {
-                    document_item_info(cx, item, Some(parent))
-                        .render_into(&mut info_buffer)
-                        .unwrap();
-                    if rendering_params.show_def_docs {
-                        write_str(
-                            &mut doc_buffer,
-                            format_args!("{}", document_full(item, cx, HeadingOffset::H5)),
-                        );
-                        short_documented = false;
-                    }
+                    write_str(
+                        &mut doc_buffer,
+                        format_args!(
+                            "{}",
+                            document_short(item, cx, link, parent, rendering_params.show_def_docs)
+                        ),
+                    );
                 }
-            } else {
+            }
+            let w = if short_documented && trait_.is_some() { interesting } else { boring };
+
+            let toggled = !doc_buffer.is_empty();
+            if toggled {
+                let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" };
                 write_str(
-                    &mut doc_buffer,
-                    format_args!(
-                        "{}",
-                        document_short(item, cx, link, parent, rendering_params.show_def_docs)
-                    ),
+                    w,
+                    format_args!("<details class=\"toggle{method_toggle_class}\" open><summary>"),
                 );
             }
-        }
-        let w = if short_documented && trait_.is_some() { interesting } else { boring };
-
-        let toggled = !doc_buffer.is_empty();
-        if toggled {
-            let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" };
-            write_str(
-                w,
-                format_args!("<details class=\"toggle{method_toggle_class}\" open><summary>"),
-            );
-        }
-        match &item.kind {
-            clean::MethodItem(..) | clean::RequiredMethodItem(_) => {
-                // Only render when the method is not static or we allow static methods
-                if render_method_item {
-                    let id = cx.derive_id(format!("{item_type}.{name}"));
-                    let source_id = trait_
-                        .and_then(|trait_| {
-                            trait_
-                                .items
-                                .iter()
-                                .find(|item| item.name.map(|n| n == *name).unwrap_or(false))
-                        })
-                        .map(|item| format!("{}.{name}", item.type_()));
+            match &item.kind {
+                clean::MethodItem(..) | clean::RequiredMethodItem(_) => {
+                    // Only render when the method is not static or we allow static methods
+                    if render_method_item {
+                        let id = cx.derive_id(format!("{item_type}.{name}"));
+                        let source_id = trait_
+                            .and_then(|trait_| {
+                                trait_
+                                    .items
+                                    .iter()
+                                    .find(|item| item.name.map(|n| n == *name).unwrap_or(false))
+                            })
+                            .map(|item| format!("{}.{name}", item.type_()));
+                        write_str(
+                            w,
+                            format_args!(
+                                "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">\
+                                {}",
+                                render_rightside(cx, item, render_mode)
+                            ),
+                        );
+                        if trait_.is_some() {
+                            // Anchors are only used on trait impls.
+                            write_str(w, format_args!("<a href=\"#{id}\" class=\"anchor\">§</a>"));
+                        }
+                        write_str(
+                            w,
+                            format_args!(
+                                "<h4 class=\"code-header\">{}</h4></section>",
+                                render_assoc_item(
+                                    item,
+                                    link.anchor(source_id.as_ref().unwrap_or(&id)),
+                                    ItemType::Impl,
+                                    cx,
+                                    render_mode,
+                                ),
+                            ),
+                        );
+                    }
+                }
+                clean::RequiredAssocConstItem(generics, ty) => {
+                    let source_id = format!("{item_type}.{name}");
+                    let id = cx.derive_id(&source_id);
                     write_str(
                         w,
-                        format_args!("<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">"),
+                        format_args!(
+                            "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">\
+                            {}",
+                            render_rightside(cx, item, render_mode)
+                        ),
                     );
-                    render_rightside(w, cx, item, render_mode);
                     if trait_.is_some() {
                         // Anchors are only used on trait impls.
                         write_str(w, format_args!("<a href=\"#{id}\" class=\"anchor\">§</a>"));
                     }
-                    w.push_str("<h4 class=\"code-header\">");
-                    render_assoc_item(
+                    write_str(
                         w,
-                        item,
-                        link.anchor(source_id.as_ref().unwrap_or(&id)),
-                        ItemType::Impl,
-                        cx,
-                        render_mode,
+                        format_args!(
+                            "<h4 class=\"code-header\">{}</h4></section>",
+                            assoc_const(
+                                item,
+                                generics,
+                                ty,
+                                AssocConstValue::None,
+                                link.anchor(if trait_.is_some() { &source_id } else { &id }),
+                                0,
+                                cx,
+                            )
+                        ),
                     );
-                    w.push_str("</h4></section>");
                 }
-            }
-            clean::RequiredAssocConstItem(ref generics, ref ty) => {
-                let source_id = format!("{item_type}.{name}");
-                let id = cx.derive_id(&source_id);
-                write_str(
-                    w,
-                    format_args!("<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">"),
-                );
-                render_rightside(w, cx, item, render_mode);
-                if trait_.is_some() {
-                    // Anchors are only used on trait impls.
-                    write_str(w, format_args!("<a href=\"#{id}\" class=\"anchor\">§</a>"));
+                clean::ProvidedAssocConstItem(ci) | clean::ImplAssocConstItem(ci) => {
+                    let source_id = format!("{item_type}.{name}");
+                    let id = cx.derive_id(&source_id);
+                    write_str(
+                        w,
+                        format_args!(
+                            "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">\
+                            {}",
+                            render_rightside(cx, item, render_mode)
+                        ),
+                    );
+                    if trait_.is_some() {
+                        // Anchors are only used on trait impls.
+                        write_str(w, format_args!("<a href=\"#{id}\" class=\"anchor\">§</a>"));
+                    }
+                    write_str(
+                        w,
+                        format_args!(
+                            "<h4 class=\"code-header\">{}</h4></section>",
+                            assoc_const(
+                                item,
+                                &ci.generics,
+                                &ci.type_,
+                                match item.kind {
+                                    clean::ProvidedAssocConstItem(_) =>
+                                        AssocConstValue::TraitDefault(&ci.kind),
+                                    clean::ImplAssocConstItem(_) => AssocConstValue::Impl(&ci.kind),
+                                    _ => unreachable!(),
+                                },
+                                link.anchor(if trait_.is_some() { &source_id } else { &id }),
+                                0,
+                                cx,
+                            )
+                        ),
+                    );
                 }
-                w.push_str("<h4 class=\"code-header\">");
-                assoc_const(
-                    w,
-                    item,
-                    generics,
-                    ty,
-                    AssocConstValue::None,
-                    link.anchor(if trait_.is_some() { &source_id } else { &id }),
-                    0,
-                    cx,
-                );
-                w.push_str("</h4></section>");
-            }
-            clean::ProvidedAssocConstItem(ci) | clean::ImplAssocConstItem(ci) => {
-                let source_id = format!("{item_type}.{name}");
-                let id = cx.derive_id(&source_id);
-                write_str(
-                    w,
-                    format_args!("<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">"),
-                );
-                render_rightside(w, cx, item, render_mode);
-                if trait_.is_some() {
-                    // Anchors are only used on trait impls.
-                    write_str(w, format_args!("<a href=\"#{id}\" class=\"anchor\">§</a>"));
+                clean::RequiredAssocTypeItem(generics, bounds) => {
+                    let source_id = format!("{item_type}.{name}");
+                    let id = cx.derive_id(&source_id);
+                    write_str(
+                        w,
+                        format_args!(
+                            "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">\
+                            {}",
+                            render_rightside(cx, item, render_mode)
+                        ),
+                    );
+                    if trait_.is_some() {
+                        // Anchors are only used on trait impls.
+                        write_str(w, format_args!("<a href=\"#{id}\" class=\"anchor\">§</a>"));
+                    }
+                    write_str(
+                        w,
+                        format_args!(
+                            "<h4 class=\"code-header\">{}</h4></section>",
+                            assoc_type(
+                                item,
+                                generics,
+                                bounds,
+                                None,
+                                link.anchor(if trait_.is_some() { &source_id } else { &id }),
+                                0,
+                                cx,
+                            )
+                        ),
+                    );
                 }
-                w.push_str("<h4 class=\"code-header\">");
-                assoc_const(
-                    w,
-                    item,
-                    &ci.generics,
-                    &ci.type_,
-                    match item.kind {
-                        clean::ProvidedAssocConstItem(_) => AssocConstValue::TraitDefault(&ci.kind),
-                        clean::ImplAssocConstItem(_) => AssocConstValue::Impl(&ci.kind),
-                        _ => unreachable!(),
-                    },
-                    link.anchor(if trait_.is_some() { &source_id } else { &id }),
-                    0,
-                    cx,
-                );
-                w.push_str("</h4></section>");
+                clean::AssocTypeItem(tydef, _bounds) => {
+                    let source_id = format!("{item_type}.{name}");
+                    let id = cx.derive_id(&source_id);
+                    write_str(
+                        w,
+                        format_args!(
+                            "<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">\
+                            {}",
+                            render_rightside(cx, item, render_mode)
+                        ),
+                    );
+                    if trait_.is_some() {
+                        // Anchors are only used on trait impls.
+                        write_str(w, format_args!("<a href=\"#{id}\" class=\"anchor\">§</a>"));
+                    }
+                    write_str(
+                        w,
+                        format_args!(
+                            "<h4 class=\"code-header\">{}</h4></section>",
+                            assoc_type(
+                                item,
+                                &tydef.generics,
+                                &[], // intentionally leaving out bounds
+                                Some(tydef.item_type.as_ref().unwrap_or(&tydef.type_)),
+                                link.anchor(if trait_.is_some() { &source_id } else { &id }),
+                                0,
+                                cx,
+                            )
+                        ),
+                    );
+                }
+                clean::StrippedItem(..) => return,
+                _ => panic!("can't make docs for trait item with name {:?}", item.name),
             }
-            clean::RequiredAssocTypeItem(ref generics, ref bounds) => {
-                let source_id = format!("{item_type}.{name}");
-                let id = cx.derive_id(&source_id);
-                write_str(
-                    w,
-                    format_args!("<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">"),
-                );
-                render_rightside(w, cx, item, render_mode);
-                if trait_.is_some() {
-                    // Anchors are only used on trait impls.
-                    write_str(w, format_args!("<a href=\"#{id}\" class=\"anchor\">§</a>"));
+
+            w.push_str(&info_buffer);
+            if toggled {
+                w.push_str("</summary>");
+                w.push_str(&doc_buffer);
+                w.push_str("</details>");
+            }
+        }
+
+        let mut impl_items = String::new();
+        let mut default_impl_items = String::new();
+        let impl_ = i.inner_impl();
+
+        // Impl items are grouped by kinds:
+        //
+        // 1. Constants
+        // 2. Types
+        // 3. Functions
+        //
+        // This order is because you can have associated constants used in associated types (like array
+        // length), and both in associcated functions. So with this order, when reading from top to
+        // bottom, you should see items definitions before they're actually used most of the time.
+        let mut assoc_types = Vec::new();
+        let mut methods = Vec::new();
+
+        if !impl_.is_negative_trait_impl() {
+            for trait_item in &impl_.items {
+                match trait_item.kind {
+                    clean::MethodItem(..) | clean::RequiredMethodItem(_) => {
+                        methods.push(trait_item)
+                    }
+                    clean::RequiredAssocTypeItem(..) | clean::AssocTypeItem(..) => {
+                        assoc_types.push(trait_item)
+                    }
+                    clean::RequiredAssocConstItem(..)
+                    | clean::ProvidedAssocConstItem(_)
+                    | clean::ImplAssocConstItem(_) => {
+                        // We render it directly since they're supposed to come first.
+                        doc_impl_item(
+                            &mut default_impl_items,
+                            &mut impl_items,
+                            cx,
+                            trait_item,
+                            if trait_.is_some() { &i.impl_item } else { parent },
+                            link,
+                            render_mode,
+                            false,
+                            trait_,
+                            rendering_params,
+                        );
+                    }
+                    _ => {}
                 }
-                w.push_str("<h4 class=\"code-header\">");
-                assoc_type(
-                    w,
-                    item,
-                    generics,
-                    bounds,
-                    None,
-                    link.anchor(if trait_.is_some() { &source_id } else { &id }),
-                    0,
+            }
+
+            for assoc_type in assoc_types {
+                doc_impl_item(
+                    &mut default_impl_items,
+                    &mut impl_items,
                     cx,
+                    assoc_type,
+                    if trait_.is_some() { &i.impl_item } else { parent },
+                    link,
+                    render_mode,
+                    false,
+                    trait_,
+                    rendering_params,
                 );
-                w.push_str("</h4></section>");
             }
-            clean::AssocTypeItem(tydef, _bounds) => {
-                let source_id = format!("{item_type}.{name}");
-                let id = cx.derive_id(&source_id);
-                write_str(
-                    w,
-                    format_args!("<section id=\"{id}\" class=\"{item_type}{in_trait_class}\">"),
-                );
-                render_rightside(w, cx, item, render_mode);
-                if trait_.is_some() {
-                    // Anchors are only used on trait impls.
-                    write_str(w, format_args!("<a href=\"#{id}\" class=\"anchor\">§</a>"));
-                }
-                w.push_str("<h4 class=\"code-header\">");
-                assoc_type(
-                    w,
-                    item,
-                    &tydef.generics,
-                    &[], // intentionally leaving out bounds
-                    Some(tydef.item_type.as_ref().unwrap_or(&tydef.type_)),
-                    link.anchor(if trait_.is_some() { &source_id } else { &id }),
-                    0,
+            for method in methods {
+                doc_impl_item(
+                    &mut default_impl_items,
+                    &mut impl_items,
                     cx,
+                    method,
+                    if trait_.is_some() { &i.impl_item } else { parent },
+                    link,
+                    render_mode,
+                    false,
+                    trait_,
+                    rendering_params,
                 );
-                w.push_str("</h4></section>");
             }
-            clean::StrippedItem(..) => return,
-            _ => panic!("can't make docs for trait item with name {:?}", item.name),
         }
 
-        w.push_str(&info_buffer);
-        if toggled {
-            w.push_str("</summary>");
-            w.push_str(&doc_buffer);
-            w.push_str("</details>");
-        }
-    }
-
-    let mut impl_items = String::new();
-    let mut default_impl_items = String::new();
-    let impl_ = i.inner_impl();
-
-    // Impl items are grouped by kinds:
-    //
-    // 1. Constants
-    // 2. Types
-    // 3. Functions
-    //
-    // This order is because you can have associated constants used in associated types (like array
-    // length), and both in associcated functions. So with this order, when reading from top to
-    // bottom, you should see items definitions before they're actually used most of the time.
-    let mut assoc_types = Vec::new();
-    let mut methods = Vec::new();
-
-    if !impl_.is_negative_trait_impl() {
-        for trait_item in &impl_.items {
-            match trait_item.kind {
-                clean::MethodItem(..) | clean::RequiredMethodItem(_) => methods.push(trait_item),
-                clean::RequiredAssocTypeItem(..) | clean::AssocTypeItem(..) => {
-                    assoc_types.push(trait_item)
+        fn render_default_items(
+            boring: &mut String,
+            interesting: &mut String,
+            cx: &Context<'_>,
+            t: &clean::Trait,
+            i: &clean::Impl,
+            parent: &clean::Item,
+            render_mode: RenderMode,
+            rendering_params: ImplRenderingParameters,
+        ) {
+            for trait_item in &t.items {
+                // Skip over any default trait items that are impossible to reference
+                // (e.g. if it has a `Self: Sized` bound on an unsized type).
+                if let Some(impl_def_id) = parent.item_id.as_def_id()
+                    && let Some(trait_item_def_id) = trait_item.item_id.as_def_id()
+                    && cx.tcx().is_impossible_associated_item((impl_def_id, trait_item_def_id))
+                {
+                    continue;
                 }
-                clean::RequiredAssocConstItem(..)
-                | clean::ProvidedAssocConstItem(_)
-                | clean::ImplAssocConstItem(_) => {
-                    // We render it directly since they're supposed to come first.
-                    doc_impl_item(
-                        &mut default_impl_items,
-                        &mut impl_items,
-                        cx,
-                        trait_item,
-                        if trait_.is_some() { &i.impl_item } else { parent },
-                        link,
-                        render_mode,
-                        false,
-                        trait_,
-                        rendering_params,
-                    );
+
+                let n = trait_item.name;
+                if i.items.iter().any(|m| m.name == n) {
+                    continue;
                 }
-                _ => {}
-            }
-        }
+                let did = i.trait_.as_ref().unwrap().def_id();
+                let provided_methods = i.provided_trait_methods(cx.tcx());
+                let assoc_link = AssocItemLink::GotoSource(did.into(), &provided_methods);
 
-        for assoc_type in assoc_types {
-            doc_impl_item(
-                &mut default_impl_items,
-                &mut impl_items,
-                cx,
-                assoc_type,
-                if trait_.is_some() { &i.impl_item } else { parent },
-                link,
-                render_mode,
-                false,
-                trait_,
-                rendering_params,
-            );
-        }
-        for method in methods {
-            doc_impl_item(
-                &mut default_impl_items,
-                &mut impl_items,
-                cx,
-                method,
-                if trait_.is_some() { &i.impl_item } else { parent },
-                link,
-                render_mode,
-                false,
-                trait_,
-                rendering_params,
-            );
+                doc_impl_item(
+                    boring,
+                    interesting,
+                    cx,
+                    trait_item,
+                    parent,
+                    assoc_link,
+                    render_mode,
+                    true,
+                    Some(t),
+                    rendering_params,
+                );
+            }
         }
-    }
 
-    fn render_default_items(
-        boring: &mut String,
-        interesting: &mut String,
-        cx: &Context<'_>,
-        t: &clean::Trait,
-        i: &clean::Impl,
-        parent: &clean::Item,
-        render_mode: RenderMode,
-        rendering_params: ImplRenderingParameters,
-    ) {
-        for trait_item in &t.items {
-            // Skip over any default trait items that are impossible to reference
-            // (e.g. if it has a `Self: Sized` bound on an unsized type).
-            if let Some(impl_def_id) = parent.item_id.as_def_id()
-                && let Some(trait_item_def_id) = trait_item.item_id.as_def_id()
-                && cx.tcx().is_impossible_associated_item((impl_def_id, trait_item_def_id))
+        // If we've implemented a trait, then also emit documentation for all
+        // default items which weren't overridden in the implementation block.
+        // We don't emit documentation for default items if they appear in the
+        // Implementations on Foreign Types or Implementors sections.
+        if rendering_params.show_default_items {
+            if let Some(t) = trait_
+                && !impl_.is_negative_trait_impl()
             {
-                continue;
-            }
-
-            let n = trait_item.name;
-            if i.items.iter().any(|m| m.name == n) {
-                continue;
+                render_default_items(
+                    &mut default_impl_items,
+                    &mut impl_items,
+                    cx,
+                    t,
+                    impl_,
+                    &i.impl_item,
+                    render_mode,
+                    rendering_params,
+                );
             }
-            let did = i.trait_.as_ref().unwrap().def_id();
-            let provided_methods = i.provided_trait_methods(cx.tcx());
-            let assoc_link = AssocItemLink::GotoSource(did.into(), &provided_methods);
-
-            doc_impl_item(
-                boring,
-                interesting,
-                cx,
-                trait_item,
-                parent,
-                assoc_link,
-                render_mode,
-                true,
-                Some(t),
-                rendering_params,
-            );
-        }
-    }
-
-    // If we've implemented a trait, then also emit documentation for all
-    // default items which weren't overridden in the implementation block.
-    // We don't emit documentation for default items if they appear in the
-    // Implementations on Foreign Types or Implementors sections.
-    if rendering_params.show_default_items {
-        if let Some(t) = trait_
-            && !impl_.is_negative_trait_impl()
-        {
-            render_default_items(
-                &mut default_impl_items,
-                &mut impl_items,
-                cx,
-                t,
-                impl_,
-                &i.impl_item,
-                render_mode,
-                rendering_params,
-            );
         }
-    }
-    if render_mode == RenderMode::Normal {
-        let toggled = !(impl_items.is_empty() && default_impl_items.is_empty());
-        if toggled {
-            close_tags.push("</details>");
-            write_str(
-                w,
-                format_args!(
+        if render_mode == RenderMode::Normal {
+            let toggled = !(impl_items.is_empty() && default_impl_items.is_empty());
+            if toggled {
+                close_tags.push("</details>");
+                write!(
+                    w,
                     "<details class=\"toggle implementors-toggle\"{}>\
                         <summary>",
                     if rendering_params.toggle_open_by_default { " open" } else { "" }
-                ),
-            );
-        }
+                )?;
+            }
 
-        let (before_dox, after_dox) = i
-            .impl_item
-            .opt_doc_value()
-            .map(|dox| {
-                Markdown {
-                    content: &dox,
-                    links: &i.impl_item.links(cx),
-                    ids: &mut cx.id_map.borrow_mut(),
-                    error_codes: cx.shared.codes,
-                    edition: cx.shared.edition(),
-                    playground: &cx.shared.playground,
-                    heading_offset: HeadingOffset::H4,
-                }
-                .split_summary_and_content()
-            })
-            .unwrap_or((None, None));
-        render_impl_summary(
-            w,
-            cx,
-            i,
-            parent,
-            rendering_params.show_def_docs,
-            use_absolute,
-            aliases,
-            &before_dox,
-        );
-        if toggled {
-            w.push_str("</summary>");
-        }
+            let (before_dox, after_dox) = i
+                .impl_item
+                .opt_doc_value()
+                .map(|dox| {
+                    Markdown {
+                        content: &dox,
+                        links: &i.impl_item.links(cx),
+                        ids: &mut cx.id_map.borrow_mut(),
+                        error_codes: cx.shared.codes,
+                        edition: cx.shared.edition(),
+                        playground: &cx.shared.playground,
+                        heading_offset: HeadingOffset::H4,
+                    }
+                    .split_summary_and_content()
+                })
+                .unwrap_or((None, None));
+            write!(
+                w,
+                "{}",
+                render_impl_summary(
+                    cx,
+                    i,
+                    parent,
+                    rendering_params.show_def_docs,
+                    use_absolute,
+                    aliases,
+                    before_dox.as_deref(),
+                )
+            )?;
+            if toggled {
+                w.write_str("</summary>")?;
+            }
 
-        if before_dox.is_some() {
-            if trait_.is_none() && impl_.items.is_empty() {
-                w.push_str(
-                    "<div class=\"item-info\">\
+            if before_dox.is_some() {
+                if trait_.is_none() && impl_.items.is_empty() {
+                    w.write_str(
+                        "<div class=\"item-info\">\
                          <div class=\"stab empty-impl\">This impl block contains no items.</div>\
                      </div>",
-                );
+                    )?;
+                }
+                if let Some(after_dox) = after_dox {
+                    write!(w, "<div class=\"docblock\">{after_dox}</div>")?;
+                }
             }
-            if let Some(after_dox) = after_dox {
-                write_str(w, format_args!("<div class=\"docblock\">{after_dox}</div>"));
+            if !default_impl_items.is_empty() || !impl_items.is_empty() {
+                w.write_str("<div class=\"impl-items\">")?;
+                close_tags.push("</div>");
             }
         }
         if !default_impl_items.is_empty() || !impl_items.is_empty() {
-            w.push_str("<div class=\"impl-items\">");
-            close_tags.push("</div>");
+            w.write_str(&default_impl_items)?;
+            w.write_str(&impl_items)?;
         }
-    }
-    if !default_impl_items.is_empty() || !impl_items.is_empty() {
-        w.push_str(&default_impl_items);
-        w.push_str(&impl_items);
-    }
-    for tag in close_tags.into_iter().rev() {
-        w.push_str(tag);
-    }
+        for tag in close_tags.into_iter().rev() {
+            w.write_str(tag)?;
+        }
+        Ok(())
+    })
 }
 
 // Render the items that appear on the right side of methods, impls, and
 // associated types. For example "1.0.0 (const: 1.39.0) · source".
-fn render_rightside(w: &mut String, cx: &Context<'_>, item: &clean::Item, render_mode: RenderMode) {
+fn render_rightside(
+    cx: &Context<'_>,
+    item: &clean::Item,
+    render_mode: RenderMode,
+) -> impl fmt::Display {
     let tcx = cx.tcx();
 
-    // FIXME: Once https://github.com/rust-lang/rust/issues/67792 is implemented, we can remove
-    // this condition.
-    let const_stability = match render_mode {
-        RenderMode::Normal => item.const_stability(tcx),
-        RenderMode::ForDeref { .. } => None,
-    };
-    let src_href = cx.src_href(item);
-    let has_src_ref = src_href.is_some();
-
-    let mut rightside = String::new();
-    let has_stability = render_stability_since_raw_with_extra(
-        &mut rightside,
-        item.stable_since(tcx),
-        const_stability,
-        if has_src_ref { "" } else { " rightside" },
-    );
-    if let Some(link) = src_href {
-        if has_stability {
-            write_str(
-                &mut rightside,
-                format_args!(" · <a class=\"src\" href=\"{link}\">Source</a>"),
-            );
-        } else {
-            write_str(
-                &mut rightside,
-                format_args!("<a class=\"src rightside\" href=\"{link}\">Source</a>"),
-            );
+    fmt::from_fn(move |w| {
+        // FIXME: Once https://github.com/rust-lang/rust/issues/67792 is implemented, we can remove
+        // this condition.
+        let const_stability = match render_mode {
+            RenderMode::Normal => item.const_stability(tcx),
+            RenderMode::ForDeref { .. } => None,
+        };
+        let src_href = cx.src_href(item);
+        let stability = render_stability_since_raw_with_extra(
+            item.stable_since(tcx),
+            const_stability,
+            if src_href.is_some() { "" } else { " rightside" },
+        );
+
+        match (stability, src_href) {
+            (Some(stability), Some(link)) => {
+                write!(
+                    w,
+                    "<span class=\"rightside\">{stability} · <a class=\"src\" href=\"{link}\">Source</a></span>",
+                )
+            }
+            (Some(stability), None) => {
+                write!(w, "{stability}")
+            }
+            (None, Some(link)) => {
+                write!(w, "<a class=\"src rightside\" href=\"{link}\">Source</a>")
+            }
+            (None, None) => Ok(()),
         }
-    }
-    if has_stability && has_src_ref {
-        write_str(w, format_args!("<span class=\"rightside\">{rightside}</span>"));
-    } else {
-        w.push_str(&rightside);
-    }
+    })
 }
 
 pub(crate) fn render_impl_summary(
-    w: &mut String,
     cx: &Context<'_>,
     i: &Impl,
     parent: &clean::Item,
@@ -2147,67 +2178,67 @@ pub(crate) fn render_impl_summary(
     // This argument is used to reference same type with different paths to avoid duplication
     // in documentation pages for trait with automatic implementations like "Send" and "Sync".
     aliases: &[String],
-    doc: &Option<String>,
-) {
-    let inner_impl = i.inner_impl();
-    let id = cx.derive_id(get_id_for_impl(cx.tcx(), i.impl_item.item_id));
-    let aliases = (!aliases.is_empty())
-        .then_some(fmt::from_fn(|f| {
-            write!(f, " data-aliases=\"{}\"", fmt::from_fn(|f| aliases.iter().joined(",", f)))
-        }))
-        .maybe_display();
-    write_str(w, format_args!("<section id=\"{id}\" class=\"impl\"{aliases}>"));
-    render_rightside(w, cx, &i.impl_item, RenderMode::Normal);
-    write_str(
-        w,
-        format_args!(
-            "<a href=\"#{id}\" class=\"anchor\">§</a>\
-            <h3 class=\"code-header\">"
-        ),
-    );
-
-    if let Some(use_absolute) = use_absolute {
-        write_str(w, format_args!("{}", inner_impl.print(use_absolute, cx)));
-        if show_def_docs {
-            for it in &inner_impl.items {
-                if let clean::AssocTypeItem(ref tydef, ref _bounds) = it.kind {
-                    w.push_str("<div class=\"where\">  ");
-                    assoc_type(
-                        w,
-                        it,
-                        &tydef.generics,
-                        &[], // intentionally leaving out bounds
-                        Some(&tydef.type_),
-                        AssocItemLink::Anchor(None),
-                        0,
-                        cx,
-                    );
-                    w.push_str(";</div>");
+    doc: Option<&str>,
+) -> impl fmt::Display {
+    fmt::from_fn(move |w| {
+        let inner_impl = i.inner_impl();
+        let id = cx.derive_id(get_id_for_impl(cx.tcx(), i.impl_item.item_id));
+        let aliases = (!aliases.is_empty())
+            .then_some(fmt::from_fn(|f| {
+                write!(f, " data-aliases=\"{}\"", fmt::from_fn(|f| aliases.iter().joined(",", f)))
+            }))
+            .maybe_display();
+        write!(
+            w,
+            "<section id=\"{id}\" class=\"impl\"{aliases}>\
+                {}\
+                <a href=\"#{id}\" class=\"anchor\">§</a>\
+                <h3 class=\"code-header\">",
+            render_rightside(cx, &i.impl_item, RenderMode::Normal)
+        )?;
+
+        if let Some(use_absolute) = use_absolute {
+            write!(w, "{}", inner_impl.print(use_absolute, cx))?;
+            if show_def_docs {
+                for it in &inner_impl.items {
+                    if let clean::AssocTypeItem(ref tydef, ref _bounds) = it.kind {
+                        write!(
+                            w,
+                            "<div class=\"where\">  {};</div>",
+                            assoc_type(
+                                it,
+                                &tydef.generics,
+                                &[], // intentionally leaving out bounds
+                                Some(&tydef.type_),
+                                AssocItemLink::Anchor(None),
+                                0,
+                                cx,
+                            )
+                        )?;
+                    }
                 }
             }
+        } else {
+            write!(w, "{}", inner_impl.print(false, cx))?;
         }
-    } else {
-        write_str(w, format_args!("{}", inner_impl.print(false, cx)));
-    }
-    w.push_str("</h3>");
+        w.write_str("</h3>")?;
 
-    let is_trait = inner_impl.trait_.is_some();
-    if is_trait && let Some(portability) = portability(&i.impl_item, Some(parent)) {
-        write_str(
-            w,
-            format_args!(
+        let is_trait = inner_impl.trait_.is_some();
+        if is_trait && let Some(portability) = portability(&i.impl_item, Some(parent)) {
+            write!(
+                w,
                 "<span class=\"item-info\">\
-                 <div class=\"stab portability\">{portability}</div>\
-             </span>",
-            ),
-        );
-    }
+                    <div class=\"stab portability\">{portability}</div>\
+                </span>",
+            )?;
+        }
 
-    if let Some(doc) = doc {
-        write_str(w, format_args!("<div class=\"docblock\">{doc}</div>"));
-    }
+        if let Some(doc) = doc {
+            write!(w, "<div class=\"docblock\">{doc}</div>")?;
+        }
 
-    w.push_str("</section>");
+        w.write_str("</section>")
+    })
 }
 
 pub(crate) fn small_url_encode(s: String) -> String {
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index f3201147039..c599a84ee44 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -1,10 +1,9 @@
 use std::cmp::Ordering;
 use std::fmt;
-use std::fmt::Display;
+use std::fmt::{Display, Write as _};
 
 use rinja::Template;
 use rustc_abi::VariantIdx;
-use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
 use rustc_hir as hir;
 use rustc_hir::def::CtorKind;
@@ -32,7 +31,7 @@ use crate::formats::item_type::ItemType;
 use crate::html::escape::{Escape, EscapeBodyTextWithWbr};
 use crate::html::format::{
     Ending, PrintWithSpace, join_with_double_colon, print_abi_with_space,
-    print_constness_with_space, print_where_clause, visibility_print_with_space, write_str,
+    print_constness_with_space, print_where_clause, visibility_print_with_space,
 };
 use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine};
 use crate::html::render::{document_full, document_item_info};
@@ -92,44 +91,32 @@ macro_rules! item_template {
 macro_rules! item_template_methods {
     () => {};
     (document $($rest:tt)*) => {
-        fn document<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
-            fmt::from_fn(move |f| {
-                let (item, cx) = self.item_and_cx();
-                let v = document(cx, item, None, HeadingOffset::H2);
-                write!(f, "{v}")
-            })
+        fn document(&self) -> impl fmt::Display {
+            let (item, cx) = self.item_and_cx();
+            document(cx, item, None, HeadingOffset::H2)
         }
         item_template_methods!($($rest)*);
     };
     (document_type_layout $($rest:tt)*) => {
-        fn document_type_layout<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
-            fmt::from_fn(move |f| {
-                let (item, cx) = self.item_and_cx();
-                let def_id = item.item_id.expect_def_id();
-                let v = document_type_layout(cx, def_id);
-                write!(f, "{v}")
-            })
+        fn document_type_layout(&self) -> impl fmt::Display {
+            let (item, cx) = self.item_and_cx();
+            let def_id = item.item_id.expect_def_id();
+            document_type_layout(cx, def_id)
         }
         item_template_methods!($($rest)*);
     };
     (render_attributes_in_pre $($rest:tt)*) => {
-        fn render_attributes_in_pre<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
-            fmt::from_fn(move |f| {
-                let (item, cx) = self.item_and_cx();
-                let v = render_attributes_in_pre(item, "", cx);
-                write!(f, "{v}")
-            })
+        fn render_attributes_in_pre(&self) -> impl fmt::Display {
+            let (item, cx) = self.item_and_cx();
+            render_attributes_in_pre(item, "", cx)
         }
         item_template_methods!($($rest)*);
     };
     (render_assoc_items $($rest:tt)*) => {
-        fn render_assoc_items<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
-            fmt::from_fn(move |f| {
-                let (item, cx) = self.item_and_cx();
-                let def_id = item.item_id.expect_def_id();
-                let v = render_assoc_items(cx, item, def_id, AssocItemRender::All);
-                write!(f, "{v}")
-            })
+        fn render_assoc_items(&self) -> impl fmt::Display {
+            let (item, cx) = self.item_and_cx();
+            let def_id = item.item_id.expect_def_id();
+            render_assoc_items(cx, item, def_id, AssocItemRender::All)
         }
         item_template_methods!($($rest)*);
     };
@@ -162,132 +149,136 @@ struct ItemVars<'a> {
     src_href: Option<&'a str>,
 }
 
-/// Calls `print_where_clause` and returns `true` if a `where` clause was generated.
-fn print_where_clause_and_check<'a, 'tcx: 'a>(
-    buffer: &mut String,
-    gens: &'a clean::Generics,
-    cx: &'a Context<'tcx>,
-) -> bool {
-    let len_before = buffer.len();
-    write_str(buffer, format_args!("{}", print_where_clause(gens, cx, 0, Ending::Newline)));
-    len_before != buffer.len()
-}
-
-pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut String) {
+pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item) -> impl fmt::Display {
     debug_assert!(!item.is_stripped());
-    let typ = match item.kind {
-        clean::ModuleItem(_) => {
-            if item.is_crate() {
-                "Crate "
-            } else {
-                "Module "
-            }
-        }
-        clean::FunctionItem(..) | clean::ForeignFunctionItem(..) => "Function ",
-        clean::TraitItem(..) => "Trait ",
-        clean::StructItem(..) => "Struct ",
-        clean::UnionItem(..) => "Union ",
-        clean::EnumItem(..) => "Enum ",
-        clean::TypeAliasItem(..) => "Type Alias ",
-        clean::MacroItem(..) => "Macro ",
-        clean::ProcMacroItem(ref mac) => match mac.kind {
-            MacroKind::Bang => "Macro ",
-            MacroKind::Attr => "Attribute Macro ",
-            MacroKind::Derive => "Derive Macro ",
-        },
-        clean::PrimitiveItem(..) => "Primitive Type ",
-        clean::StaticItem(..) | clean::ForeignStaticItem(..) => "Static ",
-        clean::ConstantItem(..) => "Constant ",
-        clean::ForeignTypeItem => "Foreign Type ",
-        clean::KeywordItem => "Keyword ",
-        clean::TraitAliasItem(..) => "Trait Alias ",
-        _ => {
-            // We don't generate pages for any other type.
-            unreachable!();
-        }
-    };
-    let stability_since_raw = {
-        let mut buf = String::new();
-        render_stability_since_raw(
-            &mut buf,
-            item.stable_since(cx.tcx()),
-            item.const_stability(cx.tcx()),
-        );
-        buf
-    };
 
-    // Write source tag
-    //
-    // When this item is part of a `crate use` in a downstream crate, the
-    // source link in the downstream documentation will actually come back to
-    // this page, and this link will be auto-clicked. The `id` attribute is
-    // used to find the link to auto-click.
-    let src_href =
-        if cx.info.include_sources && !item.is_primitive() { cx.src_href(item) } else { None };
-
-    let path_components = if item.is_primitive() || item.is_keyword() {
-        vec![]
-    } else {
-        let cur = &cx.current;
-        let amt = if item.is_mod() { cur.len() - 1 } else { cur.len() };
-        cur.iter()
-            .enumerate()
-            .take(amt)
-            .map(|(i, component)| PathComponent {
-                path: "../".repeat(cur.len() - i - 1),
-                name: *component,
-            })
-            .collect()
-    };
+    fmt::from_fn(|buf| {
+        let typ = match item.kind {
+            clean::ModuleItem(_) => {
+                if item.is_crate() {
+                    "Crate "
+                } else {
+                    "Module "
+                }
+            }
+            clean::FunctionItem(..) | clean::ForeignFunctionItem(..) => "Function ",
+            clean::TraitItem(..) => "Trait ",
+            clean::StructItem(..) => "Struct ",
+            clean::UnionItem(..) => "Union ",
+            clean::EnumItem(..) => "Enum ",
+            clean::TypeAliasItem(..) => "Type Alias ",
+            clean::MacroItem(..) => "Macro ",
+            clean::ProcMacroItem(ref mac) => match mac.kind {
+                MacroKind::Bang => "Macro ",
+                MacroKind::Attr => "Attribute Macro ",
+                MacroKind::Derive => "Derive Macro ",
+            },
+            clean::PrimitiveItem(..) => "Primitive Type ",
+            clean::StaticItem(..) | clean::ForeignStaticItem(..) => "Static ",
+            clean::ConstantItem(..) => "Constant ",
+            clean::ForeignTypeItem => "Foreign Type ",
+            clean::KeywordItem => "Keyword ",
+            clean::TraitAliasItem(..) => "Trait Alias ",
+            _ => {
+                // We don't generate pages for any other type.
+                unreachable!();
+            }
+        };
+        let stability_since_raw =
+            render_stability_since_raw(item.stable_since(cx.tcx()), item.const_stability(cx.tcx()))
+                .maybe_display()
+                .to_string();
+
+        // Write source tag
+        //
+        // When this item is part of a `crate use` in a downstream crate, the
+        // source link in the downstream documentation will actually come back to
+        // this page, and this link will be auto-clicked. The `id` attribute is
+        // used to find the link to auto-click.
+        let src_href =
+            if cx.info.include_sources && !item.is_primitive() { cx.src_href(item) } else { None };
+
+        let path_components = if item.is_primitive() || item.is_keyword() {
+            vec![]
+        } else {
+            let cur = &cx.current;
+            let amt = if item.is_mod() { cur.len() - 1 } else { cur.len() };
+            cur.iter()
+                .enumerate()
+                .take(amt)
+                .map(|(i, component)| PathComponent {
+                    path: "../".repeat(cur.len() - i - 1),
+                    name: *component,
+                })
+                .collect()
+        };
 
-    let item_vars = ItemVars {
-        typ,
-        name: item.name.as_ref().unwrap().as_str(),
-        item_type: &item.type_().to_string(),
-        path_components,
-        stability_since_raw: &stability_since_raw,
-        src_href: src_href.as_deref(),
-    };
+        let item_vars = ItemVars {
+            typ,
+            name: item.name.as_ref().unwrap().as_str(),
+            item_type: &item.type_().to_string(),
+            path_components,
+            stability_since_raw: &stability_since_raw,
+            src_href: src_href.as_deref(),
+        };
 
-    item_vars.render_into(buf).unwrap();
+        item_vars.render_into(buf).unwrap();
 
-    match &item.kind {
-        clean::ModuleItem(ref m) => item_module(buf, cx, item, &m.items),
-        clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f, _) => {
-            item_function(buf, cx, item, f)
-        }
-        clean::TraitItem(ref t) => item_trait(buf, cx, item, t),
-        clean::StructItem(ref s) => item_struct(buf, cx, item, s),
-        clean::UnionItem(ref s) => item_union(buf, cx, item, s),
-        clean::EnumItem(ref e) => item_enum(buf, cx, item, e),
-        clean::TypeAliasItem(ref t) => item_type_alias(buf, cx, item, t),
-        clean::MacroItem(ref m) => item_macro(buf, cx, item, m),
-        clean::ProcMacroItem(ref m) => item_proc_macro(buf, cx, item, m),
-        clean::PrimitiveItem(_) => item_primitive(buf, cx, item),
-        clean::StaticItem(ref i) => item_static(buf, cx, item, i, None),
-        clean::ForeignStaticItem(ref i, safety) => item_static(buf, cx, item, i, Some(*safety)),
-        clean::ConstantItem(ci) => item_constant(buf, cx, item, &ci.generics, &ci.type_, &ci.kind),
-        clean::ForeignTypeItem => item_foreign_type(buf, cx, item),
-        clean::KeywordItem => item_keyword(buf, cx, item),
-        clean::TraitAliasItem(ref ta) => item_trait_alias(buf, cx, item, ta),
-        _ => {
-            // We don't generate pages for any other type.
-            unreachable!();
-        }
-    }
+        match &item.kind {
+            clean::ModuleItem(m) => {
+                write!(buf, "{}", item_module(cx, item, &m.items))
+            }
+            clean::FunctionItem(f) | clean::ForeignFunctionItem(f, _) => {
+                write!(buf, "{}", item_function(cx, item, f))
+            }
+            clean::TraitItem(t) => write!(buf, "{}", item_trait(cx, item, t)),
+            clean::StructItem(s) => {
+                write!(buf, "{}", item_struct(cx, item, s))
+            }
+            clean::UnionItem(s) => write!(buf, "{}", item_union(cx, item, s)),
+            clean::EnumItem(e) => write!(buf, "{}", item_enum(cx, item, e)),
+            clean::TypeAliasItem(t) => {
+                write!(buf, "{}", item_type_alias(cx, item, t))
+            }
+            clean::MacroItem(m) => write!(buf, "{}", item_macro(cx, item, m)),
+            clean::ProcMacroItem(m) => {
+                write!(buf, "{}", item_proc_macro(cx, item, m))
+            }
+            clean::PrimitiveItem(_) => write!(buf, "{}", item_primitive(cx, item)),
+            clean::StaticItem(i) => {
+                write!(buf, "{}", item_static(cx, item, i, None))
+            }
+            clean::ForeignStaticItem(i, safety) => {
+                write!(buf, "{}", item_static(cx, item, i, Some(*safety)))
+            }
+            clean::ConstantItem(ci) => {
+                write!(buf, "{}", item_constant(cx, item, &ci.generics, &ci.type_, &ci.kind))
+            }
+            clean::ForeignTypeItem => {
+                write!(buf, "{}", item_foreign_type(cx, item))
+            }
+            clean::KeywordItem => write!(buf, "{}", item_keyword(cx, item)),
+            clean::TraitAliasItem(ta) => {
+                write!(buf, "{}", item_trait_alias(cx, item, ta))
+            }
+            _ => {
+                // We don't generate pages for any other type.
+                unreachable!();
+            }
+        }?;
 
-    // Render notable-traits.js used for all methods in this module.
-    let mut types_with_notable_traits = cx.types_with_notable_traits.borrow_mut();
-    if !types_with_notable_traits.is_empty() {
-        write_str(
-            buf,
-            format_args!(
+        // Render notable-traits.js used for all methods in this module.
+        let mut types_with_notable_traits = cx.types_with_notable_traits.borrow_mut();
+        if !types_with_notable_traits.is_empty() {
+            write!(
+                buf,
                 r#"<script type="text/json" id="notable-traits-data">{}</script>"#,
-                notable_traits_json(types_with_notable_traits.iter(), cx)
-            ),
-        );
-        types_with_notable_traits.clear();
-    }
+                notable_traits_json(types_with_notable_traits.iter(), cx),
+            )?;
+            types_with_notable_traits.clear();
+        }
+        Ok(())
+    })
 }
 
 /// For large structs, enums, unions, etc, determine whether to hide their fields
@@ -314,192 +305,194 @@ trait ItemTemplate<'a, 'cx: 'a>: rinja::Template + Display {
     fn item_and_cx(&self) -> (&'a clean::Item, &'a Context<'cx>);
 }
 
-fn item_module(w: &mut String, cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) {
-    write_str(w, format_args!("{}", document(cx, item, None, HeadingOffset::H2)));
-
-    let mut not_stripped_items =
-        items.iter().filter(|i| !i.is_stripped()).enumerate().collect::<Vec<_>>();
-
-    // the order of item types in the listing
-    fn reorder(ty: ItemType) -> u8 {
-        match ty {
-            ItemType::ExternCrate => 0,
-            ItemType::Import => 1,
-            ItemType::Primitive => 2,
-            ItemType::Module => 3,
-            ItemType::Macro => 4,
-            ItemType::Struct => 5,
-            ItemType::Enum => 6,
-            ItemType::Constant => 7,
-            ItemType::Static => 8,
-            ItemType::Trait => 9,
-            ItemType::Function => 10,
-            ItemType::TypeAlias => 12,
-            ItemType::Union => 13,
-            _ => 14 + ty as u8,
+fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> impl fmt::Display {
+    fmt::from_fn(|w| {
+        write!(w, "{}", document(cx, item, None, HeadingOffset::H2))?;
+
+        let mut not_stripped_items =
+            items.iter().filter(|i| !i.is_stripped()).enumerate().collect::<Vec<_>>();
+
+        // the order of item types in the listing
+        fn reorder(ty: ItemType) -> u8 {
+            match ty {
+                ItemType::ExternCrate => 0,
+                ItemType::Import => 1,
+                ItemType::Primitive => 2,
+                ItemType::Module => 3,
+                ItemType::Macro => 4,
+                ItemType::Struct => 5,
+                ItemType::Enum => 6,
+                ItemType::Constant => 7,
+                ItemType::Static => 8,
+                ItemType::Trait => 9,
+                ItemType::Function => 10,
+                ItemType::TypeAlias => 12,
+                ItemType::Union => 13,
+                _ => 14 + ty as u8,
+            }
         }
-    }
 
-    fn cmp(i1: &clean::Item, i2: &clean::Item, tcx: TyCtxt<'_>) -> Ordering {
-        let rty1 = reorder(i1.type_());
-        let rty2 = reorder(i2.type_());
-        if rty1 != rty2 {
-            return rty1.cmp(&rty2);
-        }
-        let is_stable1 = i1.stability(tcx).as_ref().map(|s| s.level.is_stable()).unwrap_or(true);
-        let is_stable2 = i2.stability(tcx).as_ref().map(|s| s.level.is_stable()).unwrap_or(true);
-        if is_stable1 != is_stable2 {
-            // true is bigger than false in the standard bool ordering,
-            // but we actually want stable items to come first
-            return is_stable2.cmp(&is_stable1);
+        fn cmp(i1: &clean::Item, i2: &clean::Item, tcx: TyCtxt<'_>) -> Ordering {
+            let rty1 = reorder(i1.type_());
+            let rty2 = reorder(i2.type_());
+            if rty1 != rty2 {
+                return rty1.cmp(&rty2);
+            }
+            let is_stable1 =
+                i1.stability(tcx).as_ref().map(|s| s.level.is_stable()).unwrap_or(true);
+            let is_stable2 =
+                i2.stability(tcx).as_ref().map(|s| s.level.is_stable()).unwrap_or(true);
+            if is_stable1 != is_stable2 {
+                // true is bigger than false in the standard bool ordering,
+                // but we actually want stable items to come first
+                return is_stable2.cmp(&is_stable1);
+            }
+            let lhs = i1.name.unwrap_or(kw::Empty);
+            let rhs = i2.name.unwrap_or(kw::Empty);
+            compare_names(lhs.as_str(), rhs.as_str())
         }
-        let lhs = i1.name.unwrap_or(kw::Empty);
-        let rhs = i2.name.unwrap_or(kw::Empty);
-        compare_names(lhs.as_str(), rhs.as_str())
-    }
 
-    let tcx = cx.tcx();
+        let tcx = cx.tcx();
 
-    match cx.shared.module_sorting {
-        ModuleSorting::Alphabetical => {
-            not_stripped_items.sort_by(|(_, i1), (_, i2)| cmp(i1, i2, tcx));
-        }
-        ModuleSorting::DeclarationOrder => {}
-    }
-    // This call is to remove re-export duplicates in cases such as:
-    //
-    // ```
-    // pub(crate) mod foo {
-    //     pub(crate) mod bar {
-    //         pub(crate) trait Double { fn foo(); }
-    //     }
-    // }
-    //
-    // pub(crate) use foo::bar::*;
-    // pub(crate) use foo::*;
-    // ```
-    //
-    // `Double` will appear twice in the generated docs.
-    //
-    // FIXME: This code is quite ugly and could be improved. Small issue: DefId
-    // can be identical even if the elements are different (mostly in imports).
-    // So in case this is an import, we keep everything by adding a "unique id"
-    // (which is the position in the vector).
-    not_stripped_items.dedup_by_key(|(idx, i)| {
-        (
-            i.item_id,
-            if i.name.is_some() { Some(full_path(cx, i)) } else { None },
-            i.type_(),
-            if i.is_import() { *idx } else { 0 },
-        )
-    });
+        match cx.shared.module_sorting {
+            ModuleSorting::Alphabetical => {
+                not_stripped_items.sort_by(|(_, i1), (_, i2)| cmp(i1, i2, tcx));
+            }
+            ModuleSorting::DeclarationOrder => {}
+        }
+        // This call is to remove re-export duplicates in cases such as:
+        //
+        // ```
+        // pub(crate) mod foo {
+        //     pub(crate) mod bar {
+        //         pub(crate) trait Double { fn foo(); }
+        //     }
+        // }
+        //
+        // pub(crate) use foo::bar::*;
+        // pub(crate) use foo::*;
+        // ```
+        //
+        // `Double` will appear twice in the generated docs.
+        //
+        // FIXME: This code is quite ugly and could be improved. Small issue: DefId
+        // can be identical even if the elements are different (mostly in imports).
+        // So in case this is an import, we keep everything by adding a "unique id"
+        // (which is the position in the vector).
+        not_stripped_items.dedup_by_key(|(idx, i)| {
+            (
+                i.item_id,
+                if i.name.is_some() { Some(full_path(cx, i)) } else { None },
+                i.type_(),
+                if i.is_import() { *idx } else { 0 },
+            )
+        });
 
-    debug!("{not_stripped_items:?}");
-    let mut last_section = None;
+        debug!("{not_stripped_items:?}");
+        let mut last_section = None;
 
-    for (_, myitem) in &not_stripped_items {
-        let my_section = item_ty_to_section(myitem.type_());
-        if Some(my_section) != last_section {
-            if last_section.is_some() {
-                w.push_str(ITEM_TABLE_CLOSE);
+        for (_, myitem) in &not_stripped_items {
+            let my_section = item_ty_to_section(myitem.type_());
+            if Some(my_section) != last_section {
+                if last_section.is_some() {
+                    w.write_str(ITEM_TABLE_CLOSE)?;
+                }
+                last_section = Some(my_section);
+                let section_id = my_section.id();
+                let tag =
+                    if section_id == "reexports" { REEXPORTS_TABLE_OPEN } else { ITEM_TABLE_OPEN };
+                write!(
+                    w,
+                    "{}",
+                    write_section_heading(my_section.name(), &cx.derive_id(section_id), None, tag)
+                )?;
             }
-            last_section = Some(my_section);
-            let section_id = my_section.id();
-            let tag =
-                if section_id == "reexports" { REEXPORTS_TABLE_OPEN } else { ITEM_TABLE_OPEN };
-            write_section_heading(w, my_section.name(), &cx.derive_id(section_id), None, tag);
-        }
 
-        match myitem.kind {
-            clean::ExternCrateItem { ref src } => {
-                use crate::html::format::anchor;
+            match myitem.kind {
+                clean::ExternCrateItem { ref src } => {
+                    use crate::html::format::anchor;
 
-                match *src {
-                    Some(src) => {
-                        write_str(
-                            w,
-                            format_args!(
+                    match *src {
+                        Some(src) => {
+                            write!(
+                                w,
                                 "<dt><code>{}extern crate {} as {};",
                                 visibility_print_with_space(myitem, cx),
                                 anchor(myitem.item_id.expect_def_id(), src, cx),
                                 EscapeBodyTextWithWbr(myitem.name.unwrap().as_str())
-                            ),
-                        );
-                    }
-                    None => {
-                        write_str(
-                            w,
-                            format_args!(
+                            )?;
+                        }
+                        None => {
+                            write!(
+                                w,
                                 "<dt><code>{}extern crate {};",
                                 visibility_print_with_space(myitem, cx),
                                 anchor(myitem.item_id.expect_def_id(), myitem.name.unwrap(), cx)
-                            ),
-                        );
+                            )?;
+                        }
                     }
+                    w.write_str("</code></dt>")?;
                 }
-                w.push_str("</code></dt>");
-            }
 
-            clean::ImportItem(ref import) => {
-                let stab_tags = import.source.did.map_or_else(String::new, |import_def_id| {
-                    extra_info_tags(tcx, myitem, item, Some(import_def_id)).to_string()
-                });
+                clean::ImportItem(ref import) => {
+                    let stab_tags = import.source.did.map_or_else(String::new, |import_def_id| {
+                        extra_info_tags(tcx, myitem, item, Some(import_def_id)).to_string()
+                    });
 
-                let id = match import.kind {
-                    clean::ImportKind::Simple(s) => {
-                        format!(" id=\"{}\"", cx.derive_id(format!("reexport.{s}")))
-                    }
-                    clean::ImportKind::Glob => String::new(),
-                };
-                write_str(
-                    w,
-                    format_args!(
+                    let id = match import.kind {
+                        clean::ImportKind::Simple(s) => {
+                            format!(" id=\"{}\"", cx.derive_id(format!("reexport.{s}")))
+                        }
+                        clean::ImportKind::Glob => String::new(),
+                    };
+                    write!(
+                        w,
                         "<dt{id}>\
                             <code>{vis}{imp}</code>{stab_tags}\
                         </dt>",
                         vis = visibility_print_with_space(myitem, cx),
                         imp = import.print(cx)
-                    ),
-                );
-            }
-
-            _ => {
-                if myitem.name.is_none() {
-                    continue;
+                    )?;
                 }
 
-                let unsafety_flag = match myitem.kind {
-                    clean::FunctionItem(_) | clean::ForeignFunctionItem(..)
-                        if myitem.fn_header(tcx).unwrap().is_unsafe() =>
-                    {
-                        "<sup title=\"unsafe function\">⚠</sup>"
+                _ => {
+                    if myitem.name.is_none() {
+                        continue;
                     }
-                    clean::ForeignStaticItem(_, hir::Safety::Unsafe) => {
-                        "<sup title=\"unsafe static\">⚠</sup>"
-                    }
-                    _ => "",
-                };
 
-                let visibility_and_hidden = match myitem.visibility(tcx) {
-                    Some(ty::Visibility::Restricted(_)) => {
-                        if myitem.is_doc_hidden() {
-                            // Don't separate with a space when there are two of them
-                            "<span title=\"Restricted Visibility\">&nbsp;🔒</span><span title=\"Hidden item\">👻</span> "
-                        } else {
-                            "<span title=\"Restricted Visibility\">&nbsp;🔒</span> "
+                    let unsafety_flag = match myitem.kind {
+                        clean::FunctionItem(_) | clean::ForeignFunctionItem(..)
+                            if myitem.fn_header(tcx).unwrap().is_unsafe() =>
+                        {
+                            "<sup title=\"unsafe function\">⚠</sup>"
                         }
-                    }
-                    _ if myitem.is_doc_hidden() => "<span title=\"Hidden item\">&nbsp;👻</span> ",
-                    _ => "",
-                };
-
-                let docs =
-                    MarkdownSummaryLine(&myitem.doc_value(), &myitem.links(cx)).into_string();
-                let (docs_before, docs_after) =
-                    if docs.is_empty() { ("", "") } else { ("<dd>", "</dd>") };
-                write_str(
-                    w,
-                    format_args!(
+                        clean::ForeignStaticItem(_, hir::Safety::Unsafe) => {
+                            "<sup title=\"unsafe static\">⚠</sup>"
+                        }
+                        _ => "",
+                    };
+
+                    let visibility_and_hidden = match myitem.visibility(tcx) {
+                        Some(ty::Visibility::Restricted(_)) => {
+                            if myitem.is_doc_hidden() {
+                                // Don't separate with a space when there are two of them
+                                "<span title=\"Restricted Visibility\">&nbsp;🔒</span><span title=\"Hidden item\">👻</span> "
+                            } else {
+                                "<span title=\"Restricted Visibility\">&nbsp;🔒</span> "
+                            }
+                        }
+                        _ if myitem.is_doc_hidden() => {
+                            "<span title=\"Hidden item\">&nbsp;👻</span> "
+                        }
+                        _ => "",
+                    };
+
+                    let docs =
+                        MarkdownSummaryLine(&myitem.doc_value(), &myitem.links(cx)).into_string();
+                    let (docs_before, docs_after) =
+                        if docs.is_empty() { ("", "") } else { ("<dd>", "</dd>") };
+                    write!(
+                        w,
                         "<dt>\
                             <a class=\"{class}\" href=\"{href}\" title=\"{title}\">{name}</a>\
                             {visibility_and_hidden}\
@@ -514,27 +507,28 @@ fn item_module(w: &mut String, cx: &Context<'_>, item: &clean::Item, items: &[cl
                         unsafety_flag = unsafety_flag,
                         href = item_path(myitem.type_(), myitem.name.unwrap().as_str()),
                         title = format_args!("{} {}", myitem.type_(), full_path(cx, myitem)),
-                    ),
-                );
+                    )?;
+                }
             }
         }
-    }
 
-    if last_section.is_some() {
-        w.push_str(ITEM_TABLE_CLOSE);
-    }
+        if last_section.is_some() {
+            w.write_str(ITEM_TABLE_CLOSE)?;
+        }
+        Ok(())
+    })
 }
 
 /// Render the stability, deprecation and portability tags that are displayed in the item's summary
 /// at the module level.
-fn extra_info_tags<'a, 'tcx: 'a>(
-    tcx: TyCtxt<'tcx>,
-    item: &'a clean::Item,
-    parent: &'a clean::Item,
+fn extra_info_tags(
+    tcx: TyCtxt<'_>,
+    item: &clean::Item,
+    parent: &clean::Item,
     import_def_id: Option<DefId>,
-) -> impl Display + 'a + Captures<'tcx> {
+) -> impl Display {
     fmt::from_fn(move |f| {
-        fn tag_html<'a>(class: &'a str, title: &'a str, contents: &'a str) -> impl Display + 'a {
+        fn tag_html(class: &str, title: &str, contents: &str) -> impl Display {
             fmt::from_fn(move |f| {
                 write!(
                     f,
@@ -583,44 +577,43 @@ fn extra_info_tags<'a, 'tcx: 'a>(
     })
 }
 
-fn item_function(w: &mut String, cx: &Context<'_>, it: &clean::Item, f: &clean::Function) {
-    let tcx = cx.tcx();
-    let header = it.fn_header(tcx).expect("printing a function which isn't a function");
-    debug!(
-        "item_function/const: {:?} {:?} {:?} {:?}",
-        it.name,
-        &header.constness,
-        it.stable_since(tcx),
-        it.const_stability(tcx),
-    );
-    let constness = print_constness_with_space(
-        &header.constness,
-        it.stable_since(tcx),
-        it.const_stability(tcx),
-    );
-    let safety = header.safety.print_with_space();
-    let abi = print_abi_with_space(header.abi).to_string();
-    let asyncness = header.asyncness.print_with_space();
-    let visibility = visibility_print_with_space(it, cx).to_string();
-    let name = it.name.unwrap();
-
-    let generics_len = format!("{:#}", f.generics.print(cx)).len();
-    let header_len = "fn ".len()
-        + visibility.len()
-        + constness.len()
-        + asyncness.len()
-        + safety.len()
-        + abi.len()
-        + name.as_str().len()
-        + generics_len;
-
-    let notable_traits = notable_traits_button(&f.decl.output, cx).maybe_display();
-
-    wrap_item(w, |w| {
-        w.reserve(header_len);
-        write_str(
-            w,
-            format_args!(
+fn item_function(cx: &Context<'_>, it: &clean::Item, f: &clean::Function) -> impl fmt::Display {
+    fmt::from_fn(|w| {
+        let tcx = cx.tcx();
+        let header = it.fn_header(tcx).expect("printing a function which isn't a function");
+        debug!(
+            "item_function/const: {:?} {:?} {:?} {:?}",
+            it.name,
+            &header.constness,
+            it.stable_since(tcx),
+            it.const_stability(tcx),
+        );
+        let constness = print_constness_with_space(
+            &header.constness,
+            it.stable_since(tcx),
+            it.const_stability(tcx),
+        );
+        let safety = header.safety.print_with_space();
+        let abi = print_abi_with_space(header.abi).to_string();
+        let asyncness = header.asyncness.print_with_space();
+        let visibility = visibility_print_with_space(it, cx).to_string();
+        let name = it.name.unwrap();
+
+        let generics_len = format!("{:#}", f.generics.print(cx)).len();
+        let header_len = "fn ".len()
+            + visibility.len()
+            + constness.len()
+            + asyncness.len()
+            + safety.len()
+            + abi.len()
+            + name.as_str().len()
+            + generics_len;
+
+        let notable_traits = notable_traits_button(&f.decl.output, cx).maybe_display();
+
+        wrap_item(w, |w| {
+            write!(
+                w,
                 "{attrs}{vis}{constness}{asyncness}{safety}{abi}fn \
                 {name}{generics}{decl}{notable_traits}{where_clause}",
                 attrs = render_attributes_in_pre(it, "", cx),
@@ -631,35 +624,37 @@ fn item_function(w: &mut String, cx: &Context<'_>, it: &clean::Item, f: &clean::
                 abi = abi,
                 name = name,
                 generics = f.generics.print(cx),
-                where_clause = print_where_clause(&f.generics, cx, 0, Ending::Newline),
+                where_clause =
+                    print_where_clause(&f.generics, cx, 0, Ending::Newline).maybe_display(),
                 decl = f.decl.full_print(header_len, 0, cx),
-            ),
-        );
-    });
-    write_str(w, format_args!("{}", document(cx, it, None, HeadingOffset::H2)));
+            )
+        })?;
+        write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
+    })
 }
 
-fn item_trait(w: &mut String, cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) {
-    let tcx = cx.tcx();
-    let bounds = bounds(&t.bounds, false, cx);
-    let required_types =
-        t.items.iter().filter(|m| m.is_required_associated_type()).collect::<Vec<_>>();
-    let provided_types = t.items.iter().filter(|m| m.is_associated_type()).collect::<Vec<_>>();
-    let required_consts =
-        t.items.iter().filter(|m| m.is_required_associated_const()).collect::<Vec<_>>();
-    let provided_consts = t.items.iter().filter(|m| m.is_associated_const()).collect::<Vec<_>>();
-    let required_methods = t.items.iter().filter(|m| m.is_ty_method()).collect::<Vec<_>>();
-    let provided_methods = t.items.iter().filter(|m| m.is_method()).collect::<Vec<_>>();
-    let count_types = required_types.len() + provided_types.len();
-    let count_consts = required_consts.len() + provided_consts.len();
-    let count_methods = required_methods.len() + provided_methods.len();
-    let must_implement_one_of_functions = tcx.trait_def(t.def_id).must_implement_one_of.clone();
-
-    // Output the trait definition
-    wrap_item(w, |mut w| {
-        write_str(
-            w,
-            format_args!(
+fn item_trait(cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) -> impl fmt::Display {
+    fmt::from_fn(|w| {
+        let tcx = cx.tcx();
+        let bounds = bounds(&t.bounds, false, cx);
+        let required_types =
+            t.items.iter().filter(|m| m.is_required_associated_type()).collect::<Vec<_>>();
+        let provided_types = t.items.iter().filter(|m| m.is_associated_type()).collect::<Vec<_>>();
+        let required_consts =
+            t.items.iter().filter(|m| m.is_required_associated_const()).collect::<Vec<_>>();
+        let provided_consts =
+            t.items.iter().filter(|m| m.is_associated_const()).collect::<Vec<_>>();
+        let required_methods = t.items.iter().filter(|m| m.is_ty_method()).collect::<Vec<_>>();
+        let provided_methods = t.items.iter().filter(|m| m.is_method()).collect::<Vec<_>>();
+        let count_types = required_types.len() + provided_types.len();
+        let count_consts = required_consts.len() + provided_consts.len();
+        let count_methods = required_methods.len() + provided_methods.len();
+        let must_implement_one_of_functions = tcx.trait_def(t.def_id).must_implement_one_of.clone();
+
+        // Output the trait definition
+        wrap_item(w, |mut w| {
+            write!(
+                w,
                 "{attrs}{vis}{safety}{is_auto}trait {name}{generics}{bounds}",
                 attrs = render_attributes_in_pre(it, "", cx),
                 vis = visibility_print_with_space(it, cx),
@@ -667,747 +662,808 @@ fn item_trait(w: &mut String, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
                 is_auto = if t.is_auto(tcx) { "auto " } else { "" },
                 name = it.name.unwrap(),
                 generics = t.generics.print(cx),
-            ),
-        );
-
-        if !t.generics.where_predicates.is_empty() {
-            write_str(
-                w,
-                format_args!("{}", print_where_clause(&t.generics, cx, 0, Ending::Newline)),
-            );
-        } else {
-            w.push_str(" ");
-        }
+            )?;
 
-        if t.items.is_empty() {
-            w.push_str("{ }");
-        } else {
-            // FIXME: we should be using a derived_id for the Anchors here
-            w.push_str("{\n");
-            let mut toggle = false;
-
-            // If there are too many associated types, hide _everything_
-            if should_hide_fields(count_types) {
-                toggle = true;
-                toggle_open(
-                    &mut w,
-                    format_args!("{} associated items", count_types + count_consts + count_methods),
-                );
+            if !t.generics.where_predicates.is_empty() {
+                write!(
+                    w,
+                    "{}",
+                    print_where_clause(&t.generics, cx, 0, Ending::Newline).maybe_display()
+                )?;
+            } else {
+                w.write_char(' ')?;
             }
-            for types in [&required_types, &provided_types] {
-                for t in types {
-                    render_assoc_item(
-                        w,
-                        t,
-                        AssocItemLink::Anchor(None),
-                        ItemType::Trait,
-                        cx,
-                        RenderMode::Normal,
+
+            if t.items.is_empty() {
+                w.write_str("{ }")
+            } else {
+                // FIXME: we should be using a derived_id for the Anchors here
+                w.write_str("{\n")?;
+                let mut toggle = false;
+
+                // If there are too many associated types, hide _everything_
+                if should_hide_fields(count_types) {
+                    toggle = true;
+                    toggle_open(
+                        &mut w,
+                        format_args!(
+                            "{} associated items",
+                            count_types + count_consts + count_methods
+                        ),
                     );
-                    w.push_str(";\n");
                 }
-            }
-            // If there are too many associated constants, hide everything after them
-            // We also do this if the types + consts is large because otherwise we could
-            // render a bunch of types and _then_ a bunch of consts just because both were
-            // _just_ under the limit
-            if !toggle && should_hide_fields(count_types + count_consts) {
-                toggle = true;
-                toggle_open(
-                    &mut w,
-                    format_args!(
-                        "{count_consts} associated constant{plural_const} and \
+                for types in [&required_types, &provided_types] {
+                    for t in types {
+                        writeln!(
+                            w,
+                            "{};",
+                            render_assoc_item(
+                                t,
+                                AssocItemLink::Anchor(None),
+                                ItemType::Trait,
+                                cx,
+                                RenderMode::Normal,
+                            )
+                        )?;
+                    }
+                }
+                // If there are too many associated constants, hide everything after them
+                // We also do this if the types + consts is large because otherwise we could
+                // render a bunch of types and _then_ a bunch of consts just because both were
+                // _just_ under the limit
+                if !toggle && should_hide_fields(count_types + count_consts) {
+                    toggle = true;
+                    toggle_open(
+                        &mut w,
+                        format_args!(
+                            "{count_consts} associated constant{plural_const} and \
                          {count_methods} method{plural_method}",
-                        plural_const = pluralize(count_consts),
-                        plural_method = pluralize(count_methods),
-                    ),
-                );
-            }
-            if count_types != 0 && (count_consts != 0 || count_methods != 0) {
-                w.push_str("\n");
-            }
-            for consts in [&required_consts, &provided_consts] {
-                for c in consts {
-                    render_assoc_item(
-                        w,
-                        c,
-                        AssocItemLink::Anchor(None),
-                        ItemType::Trait,
-                        cx,
-                        RenderMode::Normal,
+                            plural_const = pluralize(count_consts),
+                            plural_method = pluralize(count_methods),
+                        ),
                     );
-                    w.push_str(";\n");
                 }
-            }
-            if !toggle && should_hide_fields(count_methods) {
-                toggle = true;
-                toggle_open(&mut w, format_args!("{count_methods} methods"));
-            }
-            if count_consts != 0 && count_methods != 0 {
-                w.push_str("\n");
-            }
-
-            if !required_methods.is_empty() {
-                write_str(
-                    w,
-                    format_args_nl!("    // Required method{}", pluralize(required_methods.len())),
-                );
-            }
-            for (pos, m) in required_methods.iter().enumerate() {
-                render_assoc_item(
-                    w,
-                    m,
-                    AssocItemLink::Anchor(None),
-                    ItemType::Trait,
-                    cx,
-                    RenderMode::Normal,
-                );
-                w.push_str(";\n");
+                if count_types != 0 && (count_consts != 0 || count_methods != 0) {
+                    w.write_str("\n")?;
+                }
+                for consts in [&required_consts, &provided_consts] {
+                    for c in consts {
+                        writeln!(
+                            w,
+                            "{};",
+                            render_assoc_item(
+                                c,
+                                AssocItemLink::Anchor(None),
+                                ItemType::Trait,
+                                cx,
+                                RenderMode::Normal,
+                            )
+                        )?;
+                    }
+                }
+                if !toggle && should_hide_fields(count_methods) {
+                    toggle = true;
+                    toggle_open(&mut w, format_args!("{count_methods} methods"));
+                }
+                if count_consts != 0 && count_methods != 0 {
+                    w.write_str("\n")?;
+                }
 
-                if pos < required_methods.len() - 1 {
-                    w.push_str("<span class=\"item-spacer\"></span>");
+                if !required_methods.is_empty() {
+                    writeln!(w, "    // Required method{}", pluralize(required_methods.len()))?;
                 }
-            }
-            if !required_methods.is_empty() && !provided_methods.is_empty() {
-                w.push_str("\n");
-            }
+                for (pos, m) in required_methods.iter().enumerate() {
+                    writeln!(
+                        w,
+                        "{};",
+                        render_assoc_item(
+                            m,
+                            AssocItemLink::Anchor(None),
+                            ItemType::Trait,
+                            cx,
+                            RenderMode::Normal,
+                        )
+                    )?;
 
-            if !provided_methods.is_empty() {
-                write_str(
-                    w,
-                    format_args_nl!("    // Provided method{}", pluralize(provided_methods.len())),
-                );
-            }
-            for (pos, m) in provided_methods.iter().enumerate() {
-                render_assoc_item(
-                    w,
-                    m,
-                    AssocItemLink::Anchor(None),
-                    ItemType::Trait,
-                    cx,
-                    RenderMode::Normal,
-                );
+                    if pos < required_methods.len() - 1 {
+                        w.write_str("<span class=\"item-spacer\"></span>")?;
+                    }
+                }
+                if !required_methods.is_empty() && !provided_methods.is_empty() {
+                    w.write_str("\n")?;
+                }
 
-                w.push_str(" { ... }\n");
+                if !provided_methods.is_empty() {
+                    writeln!(w, "    // Provided method{}", pluralize(provided_methods.len()))?;
+                }
+                for (pos, m) in provided_methods.iter().enumerate() {
+                    writeln!(
+                        w,
+                        "{} {{ ... }}",
+                        render_assoc_item(
+                            m,
+                            AssocItemLink::Anchor(None),
+                            ItemType::Trait,
+                            cx,
+                            RenderMode::Normal,
+                        )
+                    )?;
 
-                if pos < provided_methods.len() - 1 {
-                    w.push_str("<span class=\"item-spacer\"></span>");
+                    if pos < provided_methods.len() - 1 {
+                        w.write_str("<span class=\"item-spacer\"></span>")?;
+                    }
                 }
+                if toggle {
+                    toggle_close(&mut w);
+                }
+                w.write_str("}")
             }
-            if toggle {
-                toggle_close(&mut w);
-            }
-            w.push_str("}");
-        }
-    });
+        })?;
 
-    // Trait documentation
-    write_str(w, format_args!("{}", document(cx, it, None, HeadingOffset::H2)));
+        // Trait documentation
+        write!(w, "{}", document(cx, it, None, HeadingOffset::H2))?;
 
-    fn trait_item(w: &mut String, cx: &Context<'_>, m: &clean::Item, t: &clean::Item) {
-        let name = m.name.unwrap();
-        info!("Documenting {name} on {ty_name:?}", ty_name = t.name);
-        let item_type = m.type_();
-        let id = cx.derive_id(format!("{item_type}.{name}"));
+        fn trait_item(cx: &Context<'_>, m: &clean::Item, t: &clean::Item) -> impl fmt::Display {
+            fmt::from_fn(|w| {
+                let name = m.name.unwrap();
+                info!("Documenting {name} on {ty_name:?}", ty_name = t.name);
+                let item_type = m.type_();
+                let id = cx.derive_id(format!("{item_type}.{name}"));
 
-        let mut content = String::new();
-        write_str(&mut content, format_args!("{}", document_full(m, cx, HeadingOffset::H5)));
+                let content = document_full(m, cx, HeadingOffset::H5).to_string();
 
-        let toggled = !content.is_empty();
-        if toggled {
-            let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" };
-            write_str(
-                w,
-                format_args!("<details class=\"toggle{method_toggle_class}\" open><summary>"),
-            );
-        }
-        write_str(w, format_args!("<section id=\"{id}\" class=\"method\">"));
-        render_rightside(w, cx, m, RenderMode::Normal);
-        write_str(w, format_args!("<h4 class=\"code-header\">"));
-        render_assoc_item(
-            w,
-            m,
-            AssocItemLink::Anchor(Some(&id)),
-            ItemType::Impl,
-            cx,
-            RenderMode::Normal,
-        );
-        w.push_str("</h4></section>");
-        document_item_info(cx, m, Some(t)).render_into(w).unwrap();
-        if toggled {
-            write_str(w, format_args!("</summary>"));
-            w.push_str(&content);
-            write_str(w, format_args!("</details>"));
+                let toggled = !content.is_empty();
+                if toggled {
+                    let method_toggle_class =
+                        if item_type.is_method() { " method-toggle" } else { "" };
+                    write!(w, "<details class=\"toggle{method_toggle_class}\" open><summary>")?;
+                }
+                write!(
+                    w,
+                    "<section id=\"{id}\" class=\"method\">\
+                    {}\
+                    <h4 class=\"code-header\">{}</h4></section>",
+                    render_rightside(cx, m, RenderMode::Normal),
+                    render_assoc_item(
+                        m,
+                        AssocItemLink::Anchor(Some(&id)),
+                        ItemType::Impl,
+                        cx,
+                        RenderMode::Normal,
+                    )
+                )?;
+                document_item_info(cx, m, Some(t)).render_into(w).unwrap();
+                if toggled {
+                    write!(w, "</summary>{content}</details>")?;
+                }
+                Ok(())
+            })
         }
-    }
 
-    if !required_consts.is_empty() {
-        write_section_heading(
-            w,
-            "Required Associated Constants",
-            "required-associated-consts",
-            None,
-            "<div class=\"methods\">",
-        );
-        for t in required_consts {
-            trait_item(w, cx, t, it);
+        if !required_consts.is_empty() {
+            write!(
+                w,
+                "{}",
+                write_section_heading(
+                    "Required Associated Constants",
+                    "required-associated-consts",
+                    None,
+                    "<div class=\"methods\">",
+                )
+            )?;
+            for t in required_consts {
+                write!(w, "{}", trait_item(cx, t, it))?;
+            }
+            w.write_str("</div>")?;
         }
-        w.push_str("</div>");
-    }
-    if !provided_consts.is_empty() {
-        write_section_heading(
-            w,
-            "Provided Associated Constants",
-            "provided-associated-consts",
-            None,
-            "<div class=\"methods\">",
-        );
-        for t in provided_consts {
-            trait_item(w, cx, t, it);
+        if !provided_consts.is_empty() {
+            write!(
+                w,
+                "{}",
+                write_section_heading(
+                    "Provided Associated Constants",
+                    "provided-associated-consts",
+                    None,
+                    "<div class=\"methods\">",
+                )
+            )?;
+            for t in provided_consts {
+                write!(w, "{}", trait_item(cx, t, it))?;
+            }
+            w.write_str("</div>")?;
         }
-        w.push_str("</div>");
-    }
 
-    if !required_types.is_empty() {
-        write_section_heading(
-            w,
-            "Required Associated Types",
-            "required-associated-types",
-            None,
-            "<div class=\"methods\">",
-        );
-        for t in required_types {
-            trait_item(w, cx, t, it);
+        if !required_types.is_empty() {
+            write!(
+                w,
+                "{}",
+                write_section_heading(
+                    "Required Associated Types",
+                    "required-associated-types",
+                    None,
+                    "<div class=\"methods\">",
+                )
+            )?;
+            for t in required_types {
+                write!(w, "{}", trait_item(cx, t, it))?;
+            }
+            w.write_str("</div>")?;
         }
-        w.push_str("</div>");
-    }
-    if !provided_types.is_empty() {
-        write_section_heading(
-            w,
-            "Provided Associated Types",
-            "provided-associated-types",
-            None,
-            "<div class=\"methods\">",
-        );
-        for t in provided_types {
-            trait_item(w, cx, t, it);
+        if !provided_types.is_empty() {
+            write!(
+                w,
+                "{}",
+                write_section_heading(
+                    "Provided Associated Types",
+                    "provided-associated-types",
+                    None,
+                    "<div class=\"methods\">",
+                )
+            )?;
+            for t in provided_types {
+                write!(w, "{}", trait_item(cx, t, it))?;
+            }
+            w.write_str("</div>")?;
         }
-        w.push_str("</div>");
-    }
-
-    // Output the documentation for each function individually
-    if !required_methods.is_empty() || must_implement_one_of_functions.is_some() {
-        write_section_heading(
-            w,
-            "Required Methods",
-            "required-methods",
-            None,
-            "<div class=\"methods\">",
-        );
 
-        if let Some(list) = must_implement_one_of_functions.as_deref() {
-            write_str(
+        // Output the documentation for each function individually
+        if !required_methods.is_empty() || must_implement_one_of_functions.is_some() {
+            write!(
                 w,
-                format_args!(
+                "{}",
+                write_section_heading(
+                    "Required Methods",
+                    "required-methods",
+                    None,
+                    "<div class=\"methods\">",
+                )
+            )?;
+
+            if let Some(list) = must_implement_one_of_functions.as_deref() {
+                write!(
+                    w,
                     "<div class=\"stab must_implement\">At least one of the `{}` methods is required.</div>",
-                    fmt::from_fn(|f| list.iter().joined("`, `", f))
-                ),
-            );
-        }
+                    fmt::from_fn(|f| list.iter().joined("`, `", f)),
+                )?;
+            }
 
-        for m in required_methods {
-            trait_item(w, cx, m, it);
+            for m in required_methods {
+                write!(w, "{}", trait_item(cx, m, it))?;
+            }
+            w.write_str("</div>")?;
         }
-        w.push_str("</div>");
-    }
-    if !provided_methods.is_empty() {
-        write_section_heading(
-            w,
-            "Provided Methods",
-            "provided-methods",
-            None,
-            "<div class=\"methods\">",
-        );
-        for m in provided_methods {
-            trait_item(w, cx, m, it);
+        if !provided_methods.is_empty() {
+            write!(
+                w,
+                "{}",
+                write_section_heading(
+                    "Provided Methods",
+                    "provided-methods",
+                    None,
+                    "<div class=\"methods\">",
+                )
+            )?;
+            for m in provided_methods {
+                write!(w, "{}", trait_item(cx, m, it))?;
+            }
+            w.write_str("</div>")?;
         }
-        w.push_str("</div>");
-    }
 
-    // If there are methods directly on this trait object, render them here.
-    write_str(
-        w,
-        format_args!(
+        // If there are methods directly on this trait object, render them here.
+        write!(
+            w,
             "{}",
             render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
-        ),
-    );
+        )?;
 
-    let mut extern_crates = FxIndexSet::default();
+        let mut extern_crates = FxIndexSet::default();
 
-    if !t.is_dyn_compatible(cx.tcx()) {
-        write_section_heading(
-            w,
-            "Dyn Compatibility",
-            "dyn-compatibility",
-            None,
-            format!(
-                "<div class=\"dyn-compatibility-info\"><p>This trait is <b>not</b> \
-                <a href=\"{base}/reference/items/traits.html#dyn-compatibility\">dyn compatible</a>.</p>\
-                <p><i>In older versions of Rust, dyn compatibility was called \"object safety\", \
-                so this trait is not object safe.</i></p></div>",
-                base = crate::clean::utils::DOC_RUST_LANG_ORG_VERSION
-            ),
-        );
-    }
+        if !t.is_dyn_compatible(cx.tcx()) {
+            write!(
+                w,
+                "{}",
+                write_section_heading(
+                    "Dyn Compatibility",
+                    "dyn-compatibility",
+                    None,
+                    format!(
+                        "<div class=\"dyn-compatibility-info\"><p>This trait is <b>not</b> \
+                        <a href=\"{base}/reference/items/traits.html#dyn-compatibility\">dyn compatible</a>.</p>\
+                        <p><i>In older versions of Rust, dyn compatibility was called \"object safety\", \
+                        so this trait is not object safe.</i></p></div>",
+                        base = crate::clean::utils::DOC_RUST_LANG_ORG_VERSION
+                    ),
+                ),
+            )?;
+        }
 
-    if let Some(implementors) = cx.shared.cache.implementors.get(&it.item_id.expect_def_id()) {
-        // The DefId is for the first Type found with that name. The bool is
-        // if any Types with the same name but different DefId have been found.
-        let mut implementor_dups: FxHashMap<Symbol, (DefId, bool)> = FxHashMap::default();
-        for implementor in implementors {
-            if let Some(did) =
-                implementor.inner_impl().for_.without_borrowed_ref().def_id(&cx.shared.cache)
-                && !did.is_local()
-            {
-                extern_crates.insert(did.krate);
-            }
-            match implementor.inner_impl().for_.without_borrowed_ref() {
-                clean::Type::Path { ref path } if !path.is_assoc_ty() => {
-                    let did = path.def_id();
-                    let &mut (prev_did, ref mut has_duplicates) =
-                        implementor_dups.entry(path.last()).or_insert((did, false));
-                    if prev_did != did {
-                        *has_duplicates = true;
+        if let Some(implementors) = cx.shared.cache.implementors.get(&it.item_id.expect_def_id()) {
+            // The DefId is for the first Type found with that name. The bool is
+            // if any Types with the same name but different DefId have been found.
+            let mut implementor_dups: FxHashMap<Symbol, (DefId, bool)> = FxHashMap::default();
+            for implementor in implementors {
+                if let Some(did) =
+                    implementor.inner_impl().for_.without_borrowed_ref().def_id(&cx.shared.cache)
+                    && !did.is_local()
+                {
+                    extern_crates.insert(did.krate);
+                }
+                match implementor.inner_impl().for_.without_borrowed_ref() {
+                    clean::Type::Path { path } if !path.is_assoc_ty() => {
+                        let did = path.def_id();
+                        let &mut (prev_did, ref mut has_duplicates) =
+                            implementor_dups.entry(path.last()).or_insert((did, false));
+                        if prev_did != did {
+                            *has_duplicates = true;
+                        }
                     }
+                    _ => {}
                 }
-                _ => {}
             }
-        }
-
-        let (local, mut foreign) =
-            implementors.iter().partition::<Vec<_>, _>(|i| i.is_on_local_type(cx));
 
-        let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) =
-            local.iter().partition(|i| i.inner_impl().kind.is_auto());
+            let (local, mut foreign) =
+                implementors.iter().partition::<Vec<_>, _>(|i| i.is_on_local_type(cx));
 
-        synthetic.sort_by_cached_key(|i| ImplString::new(i, cx));
-        concrete.sort_by_cached_key(|i| ImplString::new(i, cx));
-        foreign.sort_by_cached_key(|i| ImplString::new(i, cx));
+            let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) =
+                local.iter().partition(|i| i.inner_impl().kind.is_auto());
 
-        if !foreign.is_empty() {
-            write_section_heading(w, "Implementations on Foreign Types", "foreign-impls", None, "");
+            synthetic.sort_by_cached_key(|i| ImplString::new(i, cx));
+            concrete.sort_by_cached_key(|i| ImplString::new(i, cx));
+            foreign.sort_by_cached_key(|i| ImplString::new(i, cx));
 
-            for implementor in foreign {
-                let provided_methods = implementor.inner_impl().provided_trait_methods(tcx);
-                let assoc_link =
-                    AssocItemLink::GotoSource(implementor.impl_item.item_id, &provided_methods);
-                render_impl(
+            if !foreign.is_empty() {
+                write!(
                     w,
-                    cx,
-                    implementor,
-                    it,
-                    assoc_link,
-                    RenderMode::Normal,
-                    None,
-                    &[],
-                    ImplRenderingParameters {
-                        show_def_docs: false,
-                        show_default_items: false,
-                        show_non_assoc_items: true,
-                        toggle_open_by_default: false,
-                    },
-                );
-            }
-        }
+                    "{}",
+                    write_section_heading(
+                        "Implementations on Foreign Types",
+                        "foreign-impls",
+                        None,
+                        ""
+                    )
+                )?;
 
-        write_section_heading(
-            w,
-            "Implementors",
-            "implementors",
-            None,
-            "<div id=\"implementors-list\">",
-        );
-        for implementor in concrete {
-            render_implementor(cx, implementor, it, w, &implementor_dups, &[]);
-        }
-        w.push_str("</div>");
+                for implementor in foreign {
+                    let provided_methods = implementor.inner_impl().provided_trait_methods(tcx);
+                    let assoc_link =
+                        AssocItemLink::GotoSource(implementor.impl_item.item_id, &provided_methods);
+                    write!(
+                        w,
+                        "{}",
+                        render_impl(
+                            cx,
+                            implementor,
+                            it,
+                            assoc_link,
+                            RenderMode::Normal,
+                            None,
+                            &[],
+                            ImplRenderingParameters {
+                                show_def_docs: false,
+                                show_default_items: false,
+                                show_non_assoc_items: true,
+                                toggle_open_by_default: false,
+                            },
+                        )
+                    )?;
+                }
+            }
 
-        if t.is_auto(tcx) {
-            write_section_heading(
+            write!(
                 w,
-                "Auto implementors",
-                "synthetic-implementors",
-                None,
-                "<div id=\"synthetic-implementors-list\">",
-            );
-            for implementor in synthetic {
-                render_implementor(
-                    cx,
-                    implementor,
-                    it,
-                    w,
-                    &implementor_dups,
-                    &collect_paths_for_type(
-                        implementor.inner_impl().for_.clone(),
-                        &cx.shared.cache,
-                    ),
-                );
+                "{}",
+                write_section_heading(
+                    "Implementors",
+                    "implementors",
+                    None,
+                    "<div id=\"implementors-list\">",
+                )
+            )?;
+            for implementor in concrete {
+                write!(w, "{}", render_implementor(cx, implementor, it, &implementor_dups, &[]))?;
             }
-            w.push_str("</div>");
-        }
-    } else {
-        // even without any implementations to write in, we still want the heading and list, so the
-        // implementors javascript file pulled in below has somewhere to write the impls into
-        write_section_heading(
-            w,
-            "Implementors",
-            "implementors",
-            None,
-            "<div id=\"implementors-list\"></div>",
-        );
+            w.write_str("</div>")?;
 
-        if t.is_auto(tcx) {
-            write_section_heading(
+            if t.is_auto(tcx) {
+                write!(
+                    w,
+                    "{}",
+                    write_section_heading(
+                        "Auto implementors",
+                        "synthetic-implementors",
+                        None,
+                        "<div id=\"synthetic-implementors-list\">",
+                    )
+                )?;
+                for implementor in synthetic {
+                    write!(
+                        w,
+                        "{}",
+                        render_implementor(
+                            cx,
+                            implementor,
+                            it,
+                            &implementor_dups,
+                            &collect_paths_for_type(
+                                implementor.inner_impl().for_.clone(),
+                                &cx.shared.cache,
+                            ),
+                        )
+                    )?;
+                }
+                w.write_str("</div>")?;
+            }
+        } else {
+            // even without any implementations to write in, we still want the heading and list, so the
+            // implementors javascript file pulled in below has somewhere to write the impls into
+            write!(
                 w,
-                "Auto implementors",
-                "synthetic-implementors",
-                None,
-                "<div id=\"synthetic-implementors-list\"></div>",
-            );
-        }
-    }
+                "{}",
+                write_section_heading(
+                    "Implementors",
+                    "implementors",
+                    None,
+                    "<div id=\"implementors-list\"></div>",
+                )
+            )?;
 
-    // [RUSTDOCIMPL] trait.impl
-    //
-    // Include implementors in crates that depend on the current crate.
-    //
-    // This is complicated by the way rustdoc is invoked, which is basically
-    // the same way rustc is invoked: it gets called, one at a time, for each
-    // crate. When building the rustdocs for the current crate, rustdoc can
-    // see crate metadata for its dependencies, but cannot see metadata for its
-    // dependents.
-    //
-    // To make this work, we generate a "hook" at this stage, and our
-    // dependents can "plug in" to it when they build. For simplicity's sake,
-    // it's [JSONP]: a JavaScript file with the data we need (and can parse),
-    // surrounded by a tiny wrapper that the Rust side ignores, but allows the
-    // JavaScript side to include without having to worry about Same Origin
-    // Policy. The code for *that* is in `write_shared.rs`.
-    //
-    // This is further complicated by `#[doc(inline)]`. We want all copies
-    // of an inlined trait to reference the same JS file, to address complex
-    // dependency graphs like this one (lower crates depend on higher crates):
-    //
-    // ```text
-    //  --------------------------------------------
-    //  |            crate A: trait Foo            |
-    //  --------------------------------------------
-    //      |                               |
-    //  --------------------------------    |
-    //  | crate B: impl A::Foo for Bar |    |
-    //  --------------------------------    |
-    //      |                               |
-    //  ---------------------------------------------
-    //  | crate C: #[doc(inline)] use A::Foo as Baz |
-    //  |          impl Baz for Quux                |
-    //  ---------------------------------------------
-    // ```
-    //
-    // Basically, we want `C::Baz` and `A::Foo` to show the same set of
-    // impls, which is easier if they both treat `/trait.impl/A/trait.Foo.js`
-    // as the Single Source of Truth.
-    //
-    // We also want the `impl Baz for Quux` to be written to
-    // `trait.Foo.js`. However, when we generate plain HTML for `C::Baz`,
-    // we're going to want to generate plain HTML for `impl Baz for Quux` too,
-    // because that'll load faster, and it's better for SEO. And we don't want
-    // the same impl to show up twice on the same page.
-    //
-    // To make this work, the trait.impl/A/trait.Foo.js JS file has a structure kinda
-    // like this:
-    //
-    // ```js
-    // JSONP({
-    // "B": {"impl A::Foo for Bar"},
-    // "C": {"impl Baz for Quux"},
-    // });
-    // ```
-    //
-    // First of all, this means we can rebuild a crate, and it'll replace its own
-    // data if something changes. That is, `rustdoc` is idempotent. The other
-    // advantage is that we can list the crates that get included in the HTML,
-    // and ignore them when doing the JavaScript-based part of rendering.
-    // So C's HTML will have something like this:
-    //
-    // ```html
-    // <script src="/trait.impl/A/trait.Foo.js"
-    //     data-ignore-extern-crates="A,B" async></script>
-    // ```
-    //
-    // And, when the JS runs, anything in data-ignore-extern-crates is known
-    // to already be in the HTML, and will be ignored.
-    //
-    // [JSONP]: https://en.wikipedia.org/wiki/JSONP
-    let mut js_src_path: UrlPartsBuilder = std::iter::repeat("..")
-        .take(cx.current.len())
-        .chain(std::iter::once("trait.impl"))
-        .collect();
-    if let Some(did) = it.item_id.as_def_id()
-        && let get_extern = { || cx.shared.cache.external_paths.get(&did).map(|s| &s.0) }
-        && let Some(fqp) = cx.shared.cache.exact_paths.get(&did).or_else(get_extern)
-    {
-        js_src_path.extend(fqp[..fqp.len() - 1].iter().copied());
-        js_src_path.push_fmt(format_args!("{}.{}.js", it.type_(), fqp.last().unwrap()));
-    } else {
-        js_src_path.extend(cx.current.iter().copied());
-        js_src_path.push_fmt(format_args!("{}.{}.js", it.type_(), it.name.unwrap()));
-    }
-    let extern_crates = fmt::from_fn(|f| {
-        if !extern_crates.is_empty() {
-            f.write_str(" data-ignore-extern-crates=\"")?;
-            extern_crates.iter().map(|&cnum| tcx.crate_name(cnum)).joined(",", f)?;
-            f.write_str("\"")?;
+            if t.is_auto(tcx) {
+                write!(
+                    w,
+                    "{}",
+                    write_section_heading(
+                        "Auto implementors",
+                        "synthetic-implementors",
+                        None,
+                        "<div id=\"synthetic-implementors-list\"></div>",
+                    )
+                )?;
+            }
         }
-        Ok(())
-    });
-    write_str(
-        w,
-        format_args!(
+
+        // [RUSTDOCIMPL] trait.impl
+        //
+        // Include implementors in crates that depend on the current crate.
+        //
+        // This is complicated by the way rustdoc is invoked, which is basically
+        // the same way rustc is invoked: it gets called, one at a time, for each
+        // crate. When building the rustdocs for the current crate, rustdoc can
+        // see crate metadata for its dependencies, but cannot see metadata for its
+        // dependents.
+        //
+        // To make this work, we generate a "hook" at this stage, and our
+        // dependents can "plug in" to it when they build. For simplicity's sake,
+        // it's [JSONP]: a JavaScript file with the data we need (and can parse),
+        // surrounded by a tiny wrapper that the Rust side ignores, but allows the
+        // JavaScript side to include without having to worry about Same Origin
+        // Policy. The code for *that* is in `write_shared.rs`.
+        //
+        // This is further complicated by `#[doc(inline)]`. We want all copies
+        // of an inlined trait to reference the same JS file, to address complex
+        // dependency graphs like this one (lower crates depend on higher crates):
+        //
+        // ```text
+        //  --------------------------------------------
+        //  |            crate A: trait Foo            |
+        //  --------------------------------------------
+        //      |                               |
+        //  --------------------------------    |
+        //  | crate B: impl A::Foo for Bar |    |
+        //  --------------------------------    |
+        //      |                               |
+        //  ---------------------------------------------
+        //  | crate C: #[doc(inline)] use A::Foo as Baz |
+        //  |          impl Baz for Quux                |
+        //  ---------------------------------------------
+        // ```
+        //
+        // Basically, we want `C::Baz` and `A::Foo` to show the same set of
+        // impls, which is easier if they both treat `/trait.impl/A/trait.Foo.js`
+        // as the Single Source of Truth.
+        //
+        // We also want the `impl Baz for Quux` to be written to
+        // `trait.Foo.js`. However, when we generate plain HTML for `C::Baz`,
+        // we're going to want to generate plain HTML for `impl Baz for Quux` too,
+        // because that'll load faster, and it's better for SEO. And we don't want
+        // the same impl to show up twice on the same page.
+        //
+        // To make this work, the trait.impl/A/trait.Foo.js JS file has a structure kinda
+        // like this:
+        //
+        // ```js
+        // JSONP({
+        // "B": {"impl A::Foo for Bar"},
+        // "C": {"impl Baz for Quux"},
+        // });
+        // ```
+        //
+        // First of all, this means we can rebuild a crate, and it'll replace its own
+        // data if something changes. That is, `rustdoc` is idempotent. The other
+        // advantage is that we can list the crates that get included in the HTML,
+        // and ignore them when doing the JavaScript-based part of rendering.
+        // So C's HTML will have something like this:
+        //
+        // ```html
+        // <script src="/trait.impl/A/trait.Foo.js"
+        //     data-ignore-extern-crates="A,B" async></script>
+        // ```
+        //
+        // And, when the JS runs, anything in data-ignore-extern-crates is known
+        // to already be in the HTML, and will be ignored.
+        //
+        // [JSONP]: https://en.wikipedia.org/wiki/JSONP
+        let mut js_src_path: UrlPartsBuilder = std::iter::repeat("..")
+            .take(cx.current.len())
+            .chain(std::iter::once("trait.impl"))
+            .collect();
+        if let Some(did) = it.item_id.as_def_id()
+            && let get_extern = { || cx.shared.cache.external_paths.get(&did).map(|s| &s.0) }
+            && let Some(fqp) = cx.shared.cache.exact_paths.get(&did).or_else(get_extern)
+        {
+            js_src_path.extend(fqp[..fqp.len() - 1].iter().copied());
+            js_src_path.push_fmt(format_args!("{}.{}.js", it.type_(), fqp.last().unwrap()));
+        } else {
+            js_src_path.extend(cx.current.iter().copied());
+            js_src_path.push_fmt(format_args!("{}.{}.js", it.type_(), it.name.unwrap()));
+        }
+        let extern_crates = fmt::from_fn(|f| {
+            if !extern_crates.is_empty() {
+                f.write_str(" data-ignore-extern-crates=\"")?;
+                extern_crates.iter().map(|&cnum| tcx.crate_name(cnum)).joined(",", f)?;
+                f.write_str("\"")?;
+            }
+            Ok(())
+        });
+        write!(
+            w,
             "<script src=\"{src}\"{extern_crates} async></script>",
             src = js_src_path.finish()
-        ),
-    );
+        )
+    })
 }
 
 fn item_trait_alias(
-    w: &mut impl fmt::Write,
     cx: &Context<'_>,
     it: &clean::Item,
     t: &clean::TraitAlias,
-) {
-    wrap_item(w, |w| {
+) -> impl fmt::Display {
+    fmt::from_fn(|w| {
+        wrap_item(w, |w| {
+            write!(
+                w,
+                "{attrs}trait {name}{generics}{where_b} = {bounds};",
+                attrs = render_attributes_in_pre(it, "", cx),
+                name = it.name.unwrap(),
+                generics = t.generics.print(cx),
+                where_b = print_where_clause(&t.generics, cx, 0, Ending::Newline).maybe_display(),
+                bounds = bounds(&t.bounds, true, cx),
+            )
+        })?;
+
+        write!(w, "{}", document(cx, it, None, HeadingOffset::H2))?;
+        // Render any items associated directly to this alias, as otherwise they
+        // won't be visible anywhere in the docs. It would be nice to also show
+        // associated items from the aliased type (see discussion in #32077), but
+        // we need #14072 to make sense of the generics.
         write!(
             w,
-            "{attrs}trait {name}{generics}{where_b} = {bounds};",
-            attrs = render_attributes_in_pre(it, "", cx),
-            name = it.name.unwrap(),
-            generics = t.generics.print(cx),
-            where_b = print_where_clause(&t.generics, cx, 0, Ending::Newline),
-            bounds = bounds(&t.bounds, true, cx),
+            "{}",
+            render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
         )
-        .unwrap();
-    });
-
-    write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap();
-    // Render any items associated directly to this alias, as otherwise they
-    // won't be visible anywhere in the docs. It would be nice to also show
-    // associated items from the aliased type (see discussion in #32077), but
-    // we need #14072 to make sense of the generics.
-    write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All))
-        .unwrap();
+    })
 }
 
-fn item_type_alias(w: &mut String, cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) {
-    wrap_item(w, |w| {
-        write_str(
-            w,
-            format_args!(
+fn item_type_alias(cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) -> impl fmt::Display {
+    fmt::from_fn(|w| {
+        wrap_item(w, |w| {
+            write!(
+                w,
                 "{attrs}{vis}type {name}{generics}{where_clause} = {type_};",
                 attrs = render_attributes_in_pre(it, "", cx),
                 vis = visibility_print_with_space(it, cx),
                 name = it.name.unwrap(),
                 generics = t.generics.print(cx),
-                where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline),
+                where_clause =
+                    print_where_clause(&t.generics, cx, 0, Ending::Newline).maybe_display(),
                 type_ = t.type_.print(cx),
-            ),
-        );
-    });
+            )
+        })?;
 
-    write_str(w, format_args!("{}", document(cx, it, None, HeadingOffset::H2)));
+        write!(w, "{}", document(cx, it, None, HeadingOffset::H2))?;
 
-    if let Some(inner_type) = &t.inner_type {
-        write_section_heading(w, "Aliased Type", "aliased-type", None, "");
+        if let Some(inner_type) = &t.inner_type {
+            write!(w, "{}", write_section_heading("Aliased Type", "aliased-type", None, ""),)?;
 
-        match inner_type {
-            clean::TypeAliasInnerType::Enum { variants, is_non_exhaustive } => {
-                let variants_iter = || variants.iter().filter(|i| !i.is_stripped());
-                let ty = cx.tcx().type_of(it.def_id().unwrap()).instantiate_identity();
-                let enum_def_id = ty.ty_adt_def().unwrap().did();
+            match inner_type {
+                clean::TypeAliasInnerType::Enum { variants, is_non_exhaustive } => {
+                    let variants_iter = || variants.iter().filter(|i| !i.is_stripped());
+                    let ty = cx.tcx().type_of(it.def_id().unwrap()).instantiate_identity();
+                    let enum_def_id = ty.ty_adt_def().unwrap().did();
 
-                wrap_item(w, |w| {
-                    let variants_len = variants.len();
-                    let variants_count = variants_iter().count();
-                    let has_stripped_entries = variants_len != variants_count;
+                    wrap_item(w, |w| {
+                        let variants_len = variants.len();
+                        let variants_count = variants_iter().count();
+                        let has_stripped_entries = variants_len != variants_count;
 
-                    write_str(w, format_args!("enum {}{}", it.name.unwrap(), t.generics.print(cx)));
-                    render_enum_fields(
-                        w,
-                        cx,
-                        Some(&t.generics),
-                        variants,
-                        variants_count,
-                        has_stripped_entries,
-                        *is_non_exhaustive,
-                        enum_def_id,
-                    )
-                });
-                item_variants(w, cx, it, variants, enum_def_id);
-            }
-            clean::TypeAliasInnerType::Union { fields } => {
-                wrap_item(w, |w| {
-                    let fields_count = fields.iter().filter(|i| !i.is_stripped()).count();
-                    let has_stripped_fields = fields.len() != fields_count;
+                        write!(
+                            w,
+                            "enum {}{}{}",
+                            it.name.unwrap(),
+                            t.generics.print(cx),
+                            render_enum_fields(
+                                cx,
+                                Some(&t.generics),
+                                variants,
+                                variants_count,
+                                has_stripped_entries,
+                                *is_non_exhaustive,
+                                enum_def_id,
+                            )
+                        )
+                    })?;
+                    write!(w, "{}", item_variants(cx, it, variants, enum_def_id))?;
+                }
+                clean::TypeAliasInnerType::Union { fields } => {
+                    wrap_item(w, |w| {
+                        let fields_count = fields.iter().filter(|i| !i.is_stripped()).count();
+                        let has_stripped_fields = fields.len() != fields_count;
 
-                    write_str(
-                        w,
-                        format_args!("union {}{}", it.name.unwrap(), t.generics.print(cx)),
-                    );
-                    render_struct_fields(
-                        w,
-                        Some(&t.generics),
-                        None,
-                        fields,
-                        "",
-                        true,
-                        has_stripped_fields,
-                        cx,
-                    );
-                });
-                item_fields(w, cx, it, fields, None);
-            }
-            clean::TypeAliasInnerType::Struct { ctor_kind, fields } => {
-                wrap_item(w, |w| {
-                    let fields_count = fields.iter().filter(|i| !i.is_stripped()).count();
-                    let has_stripped_fields = fields.len() != fields_count;
+                        write!(
+                            w,
+                            "union {}{}{}",
+                            it.name.unwrap(),
+                            t.generics.print(cx),
+                            render_struct_fields(
+                                Some(&t.generics),
+                                None,
+                                fields,
+                                "",
+                                true,
+                                has_stripped_fields,
+                                cx,
+                            ),
+                        )
+                    })?;
+                    write!(w, "{}", item_fields(cx, it, fields, None))?;
+                }
+                clean::TypeAliasInnerType::Struct { ctor_kind, fields } => {
+                    wrap_item(w, |w| {
+                        let fields_count = fields.iter().filter(|i| !i.is_stripped()).count();
+                        let has_stripped_fields = fields.len() != fields_count;
 
-                    write_str(
-                        w,
-                        format_args!("struct {}{}", it.name.unwrap(), t.generics.print(cx)),
-                    );
-                    render_struct_fields(
-                        w,
-                        Some(&t.generics),
-                        *ctor_kind,
-                        fields,
-                        "",
-                        true,
-                        has_stripped_fields,
-                        cx,
-                    );
-                });
-                item_fields(w, cx, it, fields, None);
+                        write!(
+                            w,
+                            "struct {}{}{}",
+                            it.name.unwrap(),
+                            t.generics.print(cx),
+                            render_struct_fields(
+                                Some(&t.generics),
+                                *ctor_kind,
+                                fields,
+                                "",
+                                true,
+                                has_stripped_fields,
+                                cx,
+                            ),
+                        )
+                    })?;
+                    write!(w, "{}", item_fields(cx, it, fields, None))?;
+                }
             }
         }
-    }
 
-    let def_id = it.item_id.expect_def_id();
-    // Render any items associated directly to this alias, as otherwise they
-    // won't be visible anywhere in the docs. It would be nice to also show
-    // associated items from the aliased type (see discussion in #32077), but
-    // we need #14072 to make sense of the generics.
-    write_str(w, format_args!("{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)));
-    write_str(w, format_args!("{}", document_type_layout(cx, def_id)));
-
-    // [RUSTDOCIMPL] type.impl
-    //
-    // Include type definitions from the alias target type.
-    //
-    // Earlier versions of this code worked by having `render_assoc_items`
-    // include this data directly. That generates *O*`(types*impls)` of HTML
-    // text, and some real crates have a lot of types and impls.
-    //
-    // To create the same UX without generating half a gigabyte of HTML for a
-    // crate that only contains 20 megabytes of actual documentation[^115718],
-    // rustdoc stashes these type-alias-inlined docs in a [JSONP]
-    // "database-lite". The file itself is generated in `write_shared.rs`,
-    // and hooks into functions provided by `main.js`.
-    //
-    // The format of `trait.impl` and `type.impl` JS files are superficially
-    // similar. Each line, except the JSONP wrapper itself, belongs to a crate,
-    // and they are otherwise separate (rustdoc should be idempotent). The
-    // "meat" of the file is HTML strings, so the frontend code is very simple.
-    // Links are relative to the doc root, though, so the frontend needs to fix
-    // that up, and inlined docs can reuse these files.
-    //
-    // However, there are a few differences, caused by the sophisticated
-    // features that type aliases have. Consider this crate graph:
-    //
-    // ```text
-    //  ---------------------------------
-    //  | crate A: struct Foo<T>        |
-    //  |          type Bar = Foo<i32>  |
-    //  |          impl X for Foo<i8>   |
-    //  |          impl Y for Foo<i32>  |
-    //  ---------------------------------
-    //      |
-    //  ----------------------------------
-    //  | crate B: type Baz = A::Foo<i8> |
-    //  |          type Xyy = A::Foo<i8> |
-    //  |          impl Z for Xyy        |
-    //  ----------------------------------
-    // ```
-    //
-    // The type.impl/A/struct.Foo.js JS file has a structure kinda like this:
-    //
-    // ```js
-    // JSONP({
-    // "A": [["impl Y for Foo<i32>", "Y", "A::Bar"]],
-    // "B": [["impl X for Foo<i8>", "X", "B::Baz", "B::Xyy"], ["impl Z for Xyy", "Z", "B::Baz"]],
-    // });
-    // ```
-    //
-    // When the type.impl file is loaded, only the current crate's docs are
-    // actually used. The main reason to bundle them together is that there's
-    // enough duplication in them for DEFLATE to remove the redundancy.
-    //
-    // The contents of a crate are a list of impl blocks, themselves
-    // represented as lists. The first item in the sublist is the HTML block,
-    // the second item is the name of the trait (which goes in the sidebar),
-    // and all others are the names of type aliases that successfully match.
-    //
-    // This way:
-    //
-    // - There's no need to generate these files for types that have no aliases
-    //   in the current crate. If a dependent crate makes a type alias, it'll
-    //   take care of generating its own docs.
-    // - There's no need to reimplement parts of the type checker in
-    //   JavaScript. The Rust backend does the checking, and includes its
-    //   results in the file.
-    // - Docs defined directly on the type alias are dropped directly in the
-    //   HTML by `render_assoc_items`, and are accessible without JavaScript.
-    //   The JSONP file will not list impl items that are known to be part
-    //   of the main HTML file already.
-    //
-    // [JSONP]: https://en.wikipedia.org/wiki/JSONP
-    // [^115718]: https://github.com/rust-lang/rust/issues/115718
-    let cache = &cx.shared.cache;
-    if let Some(target_did) = t.type_.def_id(cache) &&
-        let get_extern = { || cache.external_paths.get(&target_did) } &&
-        let Some(&(ref target_fqp, target_type)) = cache.paths.get(&target_did).or_else(get_extern) &&
-        target_type.is_adt() && // primitives cannot be inlined
-        let Some(self_did) = it.item_id.as_def_id() &&
-        let get_local = { || cache.paths.get(&self_did).map(|(p, _)| p) } &&
-        let Some(self_fqp) = cache.exact_paths.get(&self_did).or_else(get_local)
-    {
-        let mut js_src_path: UrlPartsBuilder = std::iter::repeat("..")
-            .take(cx.current.len())
-            .chain(std::iter::once("type.impl"))
-            .collect();
-        js_src_path.extend(target_fqp[..target_fqp.len() - 1].iter().copied());
-        js_src_path.push_fmt(format_args!("{target_type}.{}.js", target_fqp.last().unwrap()));
-        let self_path = fmt::from_fn(|f| self_fqp.iter().joined("::", f));
-        write_str(
+        let def_id = it.item_id.expect_def_id();
+        // Render any items associated directly to this alias, as otherwise they
+        // won't be visible anywhere in the docs. It would be nice to also show
+        // associated items from the aliased type (see discussion in #32077), but
+        // we need #14072 to make sense of the generics.
+        write!(
             w,
-            format_args!(
+            "{}{}",
+            render_assoc_items(cx, it, def_id, AssocItemRender::All),
+            document_type_layout(cx, def_id)
+        )?;
+
+        // [RUSTDOCIMPL] type.impl
+        //
+        // Include type definitions from the alias target type.
+        //
+        // Earlier versions of this code worked by having `render_assoc_items`
+        // include this data directly. That generates *O*`(types*impls)` of HTML
+        // text, and some real crates have a lot of types and impls.
+        //
+        // To create the same UX without generating half a gigabyte of HTML for a
+        // crate that only contains 20 megabytes of actual documentation[^115718],
+        // rustdoc stashes these type-alias-inlined docs in a [JSONP]
+        // "database-lite". The file itself is generated in `write_shared.rs`,
+        // and hooks into functions provided by `main.js`.
+        //
+        // The format of `trait.impl` and `type.impl` JS files are superficially
+        // similar. Each line, except the JSONP wrapper itself, belongs to a crate,
+        // and they are otherwise separate (rustdoc should be idempotent). The
+        // "meat" of the file is HTML strings, so the frontend code is very simple.
+        // Links are relative to the doc root, though, so the frontend needs to fix
+        // that up, and inlined docs can reuse these files.
+        //
+        // However, there are a few differences, caused by the sophisticated
+        // features that type aliases have. Consider this crate graph:
+        //
+        // ```text
+        //  ---------------------------------
+        //  | crate A: struct Foo<T>        |
+        //  |          type Bar = Foo<i32>  |
+        //  |          impl X for Foo<i8>   |
+        //  |          impl Y for Foo<i32>  |
+        //  ---------------------------------
+        //      |
+        //  ----------------------------------
+        //  | crate B: type Baz = A::Foo<i8> |
+        //  |          type Xyy = A::Foo<i8> |
+        //  |          impl Z for Xyy        |
+        //  ----------------------------------
+        // ```
+        //
+        // The type.impl/A/struct.Foo.js JS file has a structure kinda like this:
+        //
+        // ```js
+        // JSONP({
+        // "A": [["impl Y for Foo<i32>", "Y", "A::Bar"]],
+        // "B": [["impl X for Foo<i8>", "X", "B::Baz", "B::Xyy"], ["impl Z for Xyy", "Z", "B::Baz"]],
+        // });
+        // ```
+        //
+        // When the type.impl file is loaded, only the current crate's docs are
+        // actually used. The main reason to bundle them together is that there's
+        // enough duplication in them for DEFLATE to remove the redundancy.
+        //
+        // The contents of a crate are a list of impl blocks, themselves
+        // represented as lists. The first item in the sublist is the HTML block,
+        // the second item is the name of the trait (which goes in the sidebar),
+        // and all others are the names of type aliases that successfully match.
+        //
+        // This way:
+        //
+        // - There's no need to generate these files for types that have no aliases
+        //   in the current crate. If a dependent crate makes a type alias, it'll
+        //   take care of generating its own docs.
+        // - There's no need to reimplement parts of the type checker in
+        //   JavaScript. The Rust backend does the checking, and includes its
+        //   results in the file.
+        // - Docs defined directly on the type alias are dropped directly in the
+        //   HTML by `render_assoc_items`, and are accessible without JavaScript.
+        //   The JSONP file will not list impl items that are known to be part
+        //   of the main HTML file already.
+        //
+        // [JSONP]: https://en.wikipedia.org/wiki/JSONP
+        // [^115718]: https://github.com/rust-lang/rust/issues/115718
+        let cache = &cx.shared.cache;
+        if let Some(target_did) = t.type_.def_id(cache)
+            && let get_extern = { || cache.external_paths.get(&target_did) }
+            && let Some(&(ref target_fqp, target_type)) =
+                cache.paths.get(&target_did).or_else(get_extern)
+            && target_type.is_adt() // primitives cannot be inlined
+            && let Some(self_did) = it.item_id.as_def_id()
+            && let get_local = { || cache.paths.get(&self_did).map(|(p, _)| p) }
+            && let Some(self_fqp) = cache.exact_paths.get(&self_did).or_else(get_local)
+        {
+            let mut js_src_path: UrlPartsBuilder = std::iter::repeat("..")
+                .take(cx.current.len())
+                .chain(std::iter::once("type.impl"))
+                .collect();
+            js_src_path.extend(target_fqp[..target_fqp.len() - 1].iter().copied());
+            js_src_path.push_fmt(format_args!("{target_type}.{}.js", target_fqp.last().unwrap()));
+            let self_path = fmt::from_fn(|f| self_fqp.iter().joined("::", f));
+            write!(
+                w,
                 "<script src=\"{src}\" data-self-path=\"{self_path}\" async></script>",
-                src = js_src_path.finish()
-            ),
-        );
-    }
+                src = js_src_path.finish(),
+            )?;
+        }
+        Ok(())
+    })
 }
 
-fn item_union(w: &mut String, cx: &Context<'_>, it: &clean::Item, s: &clean::Union) {
+fn item_union(cx: &Context<'_>, it: &clean::Item, s: &clean::Union) -> impl fmt::Display {
     item_template!(
         #[template(path = "item_union.html")]
         struct ItemUnion<'a, 'cx> {
@@ -1419,35 +1475,20 @@ fn item_union(w: &mut String, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
     );
 
     impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> {
-        fn render_union<'b>(&'b self) -> impl Display + Captures<'a> + 'b + Captures<'cx> {
-            fmt::from_fn(move |f| {
-                let v = render_union(self.it, Some(&self.s.generics), &self.s.fields, self.cx);
-                write!(f, "{v}")
-            })
+        fn render_union(&self) -> impl Display {
+            render_union(self.it, Some(&self.s.generics), &self.s.fields, self.cx)
         }
 
-        fn document_field<'b>(
-            &'b self,
-            field: &'a clean::Item,
-        ) -> impl Display + Captures<'a> + 'b + Captures<'cx> {
-            fmt::from_fn(move |f| {
-                let v = document(self.cx, field, Some(self.it), HeadingOffset::H3);
-                write!(f, "{v}")
-            })
+        fn document_field(&self, field: &'a clean::Item) -> impl Display {
+            document(self.cx, field, Some(self.it), HeadingOffset::H3)
         }
 
         fn stability_field(&self, field: &clean::Item) -> Option<String> {
             field.stability_class(self.cx.tcx())
         }
 
-        fn print_ty<'b>(
-            &'b self,
-            ty: &'a clean::Type,
-        ) -> impl Display + Captures<'a> + 'b + Captures<'cx> {
-            fmt::from_fn(move |f| {
-                let v = ty.print(self.cx);
-                write!(f, "{v}")
-            })
+        fn print_ty(&self, ty: &'a clean::Type) -> impl Display {
+            ty.print(self.cx)
         }
 
         fn fields_iter(
@@ -1464,13 +1505,13 @@ fn item_union(w: &mut String, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
         }
     }
 
-    ItemUnion { cx, it, s }.render_into(w).unwrap();
+    fmt::from_fn(|w| {
+        ItemUnion { cx, it, s }.render_into(w).unwrap();
+        Ok(())
+    })
 }
 
-fn print_tuple_struct_fields<'a, 'cx: 'a>(
-    cx: &'a Context<'cx>,
-    s: &'a [clean::Item],
-) -> impl Display + 'a + Captures<'cx> {
+fn print_tuple_struct_fields(cx: &Context<'_>, s: &[clean::Item]) -> impl Display {
     fmt::from_fn(|f| {
         if !s.is_empty()
             && s.iter().all(|field| {
@@ -1492,40 +1533,42 @@ fn print_tuple_struct_fields<'a, 'cx: 'a>(
     })
 }
 
-fn item_enum(w: &mut String, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) {
-    let count_variants = e.variants().count();
-    wrap_item(w, |w| {
-        render_attributes_in_code(w, it, cx);
-        write_str(
-            w,
-            format_args!(
-                "{}enum {}{}",
+fn item_enum(cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) -> impl fmt::Display {
+    fmt::from_fn(|w| {
+        let count_variants = e.variants().count();
+        wrap_item(w, |w| {
+            render_attributes_in_code(w, it, cx);
+            write!(
+                w,
+                "{}enum {}{}{}",
                 visibility_print_with_space(it, cx),
                 it.name.unwrap(),
                 e.generics.print(cx),
-            ),
-        );
-
-        render_enum_fields(
-            w,
-            cx,
-            Some(&e.generics),
-            &e.variants,
-            count_variants,
-            e.has_stripped_entries(),
-            it.is_non_exhaustive(),
-            it.def_id().unwrap(),
-        );
-    });
+                render_enum_fields(
+                    cx,
+                    Some(&e.generics),
+                    &e.variants,
+                    count_variants,
+                    e.has_stripped_entries(),
+                    it.is_non_exhaustive(),
+                    it.def_id().unwrap(),
+                ),
+            )
+        })?;
 
-    write_str(w, format_args!("{}", document(cx, it, None, HeadingOffset::H2)));
+        write!(w, "{}", document(cx, it, None, HeadingOffset::H2))?;
 
-    if count_variants != 0 {
-        item_variants(w, cx, it, &e.variants, it.def_id().unwrap());
-    }
-    let def_id = it.item_id.expect_def_id();
-    write_str(w, format_args!("{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)));
-    write_str(w, format_args!("{}", document_type_layout(cx, def_id)));
+        if count_variants != 0 {
+            write!(w, "{}", item_variants(cx, it, &e.variants, it.def_id().unwrap()))?;
+        }
+        let def_id = it.item_id.expect_def_id();
+        write!(
+            w,
+            "{}{}",
+            render_assoc_items(cx, it, def_id, AssocItemRender::All),
+            document_type_layout(cx, def_id)
+        )
+    })
 }
 
 /// It'll return false if any variant is not a C-like variant. Otherwise it'll return true if at
@@ -1554,32 +1597,33 @@ fn should_show_enum_discriminant(
 }
 
 fn display_c_like_variant(
-    w: &mut String,
     cx: &Context<'_>,
     item: &clean::Item,
     variant: &clean::Variant,
     index: VariantIdx,
     should_show_enum_discriminant: bool,
     enum_def_id: DefId,
-) {
-    let name = item.name.unwrap();
-    if let Some(ref value) = variant.discriminant {
-        write_str(w, format_args!("{} = {}", name.as_str(), value.value(cx.tcx(), true)));
-    } else if should_show_enum_discriminant {
-        let adt_def = cx.tcx().adt_def(enum_def_id);
-        let discr = adt_def.discriminant_for_variant(cx.tcx(), index);
-        if discr.ty.is_signed() {
-            write_str(w, format_args!("{} = {}", name.as_str(), discr.val as i128));
+) -> impl fmt::Display {
+    fmt::from_fn(move |w| {
+        let name = item.name.unwrap();
+        if let Some(ref value) = variant.discriminant {
+            write!(w, "{} = {}", name.as_str(), value.value(cx.tcx(), true))?;
+        } else if should_show_enum_discriminant {
+            let adt_def = cx.tcx().adt_def(enum_def_id);
+            let discr = adt_def.discriminant_for_variant(cx.tcx(), index);
+            if discr.ty.is_signed() {
+                write!(w, "{} = {}", name.as_str(), discr.val as i128)?;
+            } else {
+                write!(w, "{} = {}", name.as_str(), discr.val)?;
+            }
         } else {
-            write_str(w, format_args!("{} = {}", name.as_str(), discr.val));
+            write!(w, "{name}")?;
         }
-    } else {
-        w.push_str(name.as_str());
-    }
+        Ok(())
+    })
 }
 
 fn render_enum_fields(
-    mut w: &mut String,
     cx: &Context<'_>,
     g: Option<&clean::Generics>,
     variants: &IndexVec<VariantIdx, clean::Item>,
@@ -1587,422 +1631,452 @@ fn render_enum_fields(
     has_stripped_entries: bool,
     is_non_exhaustive: bool,
     enum_def_id: DefId,
-) {
-    let should_show_enum_discriminant = should_show_enum_discriminant(cx, enum_def_id, variants);
-    if !g.is_some_and(|g| print_where_clause_and_check(w, g, cx)) {
-        // If there wasn't a `where` clause, we add a whitespace.
-        w.push_str(" ");
-    }
-
-    let variants_stripped = has_stripped_entries;
-    if count_variants == 0 && !variants_stripped {
-        w.push_str("{}");
-    } else {
-        w.push_str("{\n");
-        let toggle = should_hide_fields(count_variants);
-        if toggle {
-            toggle_open(&mut w, format_args!("{count_variants} variants"));
+) -> impl fmt::Display {
+    fmt::from_fn(move |w| {
+        let should_show_enum_discriminant =
+            should_show_enum_discriminant(cx, enum_def_id, variants);
+        if let Some(generics) = g
+            && let Some(where_clause) = print_where_clause(generics, cx, 0, Ending::Newline)
+        {
+            write!(w, "{where_clause}")?;
+        } else {
+            // If there wasn't a `where` clause, we add a whitespace.
+            w.write_char(' ')?;
         }
-        const TAB: &str = "    ";
-        for (index, v) in variants.iter_enumerated() {
-            if v.is_stripped() {
-                continue;
+
+        let variants_stripped = has_stripped_entries;
+        if count_variants == 0 && !variants_stripped {
+            w.write_str("{}")
+        } else {
+            w.write_str("{\n")?;
+            let toggle = should_hide_fields(count_variants);
+            if toggle {
+                toggle_open(&mut *w, format_args!("{count_variants} variants"));
             }
-            w.push_str(TAB);
-            match v.kind {
-                clean::VariantItem(ref var) => match var.kind {
-                    clean::VariantKind::CLike => display_c_like_variant(
-                        w,
-                        cx,
-                        v,
-                        var,
-                        index,
-                        should_show_enum_discriminant,
-                        enum_def_id,
-                    ),
-                    clean::VariantKind::Tuple(ref s) => {
-                        write_str(
-                            w,
-                            format_args!(
-                                "{}({})",
-                                v.name.unwrap(),
-                                print_tuple_struct_fields(cx, s)
-                            ),
-                        );
-                    }
-                    clean::VariantKind::Struct(ref s) => {
-                        render_struct(w, v, None, None, &s.fields, TAB, false, cx);
-                    }
-                },
-                _ => unreachable!(),
+            const TAB: &str = "    ";
+            for (index, v) in variants.iter_enumerated() {
+                if v.is_stripped() {
+                    continue;
+                }
+                w.write_str(TAB)?;
+                match v.kind {
+                    clean::VariantItem(ref var) => match var.kind {
+                        clean::VariantKind::CLike => {
+                            write!(
+                                w,
+                                "{}",
+                                display_c_like_variant(
+                                    cx,
+                                    v,
+                                    var,
+                                    index,
+                                    should_show_enum_discriminant,
+                                    enum_def_id,
+                                )
+                            )?;
+                        }
+                        clean::VariantKind::Tuple(ref s) => {
+                            write!(w, "{}({})", v.name.unwrap(), print_tuple_struct_fields(cx, s))?;
+                        }
+                        clean::VariantKind::Struct(ref s) => {
+                            write!(
+                                w,
+                                "{}",
+                                render_struct(v, None, None, &s.fields, TAB, false, cx)
+                            )?;
+                        }
+                    },
+                    _ => unreachable!(),
+                }
+                w.write_str(",\n")?;
             }
-            w.push_str(",\n");
-        }
 
-        if variants_stripped && !is_non_exhaustive {
-            w.push_str("    <span class=\"comment\">// some variants omitted</span>\n");
-        }
-        if toggle {
-            toggle_close(&mut w);
+            if variants_stripped && !is_non_exhaustive {
+                w.write_str("    <span class=\"comment\">// some variants omitted</span>\n")?;
+            }
+            if toggle {
+                toggle_close(&mut *w);
+            }
+            w.write_str("}")
         }
-        w.push_str("}");
-    }
+    })
 }
 
 fn item_variants(
-    w: &mut String,
     cx: &Context<'_>,
     it: &clean::Item,
     variants: &IndexVec<VariantIdx, clean::Item>,
     enum_def_id: DefId,
-) {
-    let tcx = cx.tcx();
-    write_section_heading(
-        w,
-        &format!("Variants{}", document_non_exhaustive_header(it)),
-        "variants",
-        Some("variants"),
-        format!("{}<div class=\"variants\">", document_non_exhaustive(it)),
-    );
-
-    let should_show_enum_discriminant = should_show_enum_discriminant(cx, enum_def_id, variants);
-    for (index, variant) in variants.iter_enumerated() {
-        if variant.is_stripped() {
-            continue;
-        }
-        let id = cx.derive_id(format!("{}.{}", ItemType::Variant, variant.name.unwrap()));
-        write_str(
+) -> impl fmt::Display {
+    fmt::from_fn(move |w| {
+        let tcx = cx.tcx();
+        write!(
             w,
-            format_args!(
-                "<section id=\"{id}\" class=\"variant\">\
-                <a href=\"#{id}\" class=\"anchor\">§</a>"
+            "{}",
+            write_section_heading(
+                &format!("Variants{}", document_non_exhaustive_header(it)),
+                "variants",
+                Some("variants"),
+                format!("{}<div class=\"variants\">", document_non_exhaustive(it)),
             ),
-        );
-        render_stability_since_raw_with_extra(
-            w,
-            variant.stable_since(tcx),
-            variant.const_stability(tcx),
-            " rightside",
-        );
-        w.push_str("<h3 class=\"code-header\">");
-        if let clean::VariantItem(ref var) = variant.kind
-            && let clean::VariantKind::CLike = var.kind
-        {
-            display_c_like_variant(
+        )?;
+
+        let should_show_enum_discriminant =
+            should_show_enum_discriminant(cx, enum_def_id, variants);
+        for (index, variant) in variants.iter_enumerated() {
+            if variant.is_stripped() {
+                continue;
+            }
+            let id = cx.derive_id(format!("{}.{}", ItemType::Variant, variant.name.unwrap()));
+            write!(
                 w,
-                cx,
-                variant,
-                var,
-                index,
-                should_show_enum_discriminant,
-                enum_def_id,
-            );
-        } else {
-            w.push_str(variant.name.unwrap().as_str());
-        }
+                "<section id=\"{id}\" class=\"variant\">\
+                    <a href=\"#{id}\" class=\"anchor\">§</a>\
+                    {}\
+                    <h3 class=\"code-header\">",
+                render_stability_since_raw_with_extra(
+                    variant.stable_since(tcx),
+                    variant.const_stability(tcx),
+                    " rightside",
+                )
+                .maybe_display()
+            )?;
+            if let clean::VariantItem(ref var) = variant.kind
+                && let clean::VariantKind::CLike = var.kind
+            {
+                write!(
+                    w,
+                    "{}",
+                    display_c_like_variant(
+                        cx,
+                        variant,
+                        var,
+                        index,
+                        should_show_enum_discriminant,
+                        enum_def_id,
+                    )
+                )?;
+            } else {
+                w.write_str(variant.name.unwrap().as_str())?;
+            }
 
-        let clean::VariantItem(variant_data) = &variant.kind else { unreachable!() };
+            let clean::VariantItem(variant_data) = &variant.kind else { unreachable!() };
 
-        if let clean::VariantKind::Tuple(ref s) = variant_data.kind {
-            write_str(w, format_args!("({})", print_tuple_struct_fields(cx, s)));
-        }
-        w.push_str("</h3></section>");
+            if let clean::VariantKind::Tuple(ref s) = variant_data.kind {
+                write!(w, "({})", print_tuple_struct_fields(cx, s))?;
+            }
+            w.write_str("</h3></section>")?;
 
-        write_str(w, format_args!("{}", document(cx, variant, Some(it), HeadingOffset::H4)));
+            write!(w, "{}", document(cx, variant, Some(it), HeadingOffset::H4))?;
 
-        let heading_and_fields = match &variant_data.kind {
-            clean::VariantKind::Struct(s) => {
-                // If there is no field to display, no need to add the heading.
-                if s.fields.iter().any(|f| !f.is_doc_hidden()) {
-                    Some(("Fields", &s.fields))
-                } else {
-                    None
+            let heading_and_fields = match &variant_data.kind {
+                clean::VariantKind::Struct(s) => {
+                    // If there is no field to display, no need to add the heading.
+                    if s.fields.iter().any(|f| !f.is_doc_hidden()) {
+                        Some(("Fields", &s.fields))
+                    } else {
+                        None
+                    }
                 }
-            }
-            clean::VariantKind::Tuple(fields) => {
-                // Documentation on tuple variant fields is rare, so to reduce noise we only emit
-                // the section if at least one field is documented.
-                if fields.iter().any(|f| !f.doc_value().is_empty()) {
-                    Some(("Tuple Fields", fields))
-                } else {
-                    None
+                clean::VariantKind::Tuple(fields) => {
+                    // Documentation on tuple variant fields is rare, so to reduce noise we only emit
+                    // the section if at least one field is documented.
+                    if fields.iter().any(|f| !f.doc_value().is_empty()) {
+                        Some(("Tuple Fields", fields))
+                    } else {
+                        None
+                    }
                 }
-            }
-            clean::VariantKind::CLike => None,
-        };
+                clean::VariantKind::CLike => None,
+            };
 
-        if let Some((heading, fields)) = heading_and_fields {
-            let variant_id =
-                cx.derive_id(format!("{}.{}.fields", ItemType::Variant, variant.name.unwrap()));
-            write_str(
-                w,
-                format_args!(
+            if let Some((heading, fields)) = heading_and_fields {
+                let variant_id =
+                    cx.derive_id(format!("{}.{}.fields", ItemType::Variant, variant.name.unwrap()));
+                write!(
+                    w,
                     "<div class=\"sub-variant\" id=\"{variant_id}\">\
                         <h4>{heading}</h4>\
                         {}",
                     document_non_exhaustive(variant)
-                ),
-            );
-            for field in fields {
-                match field.kind {
-                    clean::StrippedItem(box clean::StructFieldItem(_)) => {}
-                    clean::StructFieldItem(ref ty) => {
-                        let id = cx.derive_id(format!(
-                            "variant.{}.field.{}",
-                            variant.name.unwrap(),
-                            field.name.unwrap()
-                        ));
-                        write_str(
-                            w,
-                            format_args!(
+                )?;
+                for field in fields {
+                    match field.kind {
+                        clean::StrippedItem(box clean::StructFieldItem(_)) => {}
+                        clean::StructFieldItem(ref ty) => {
+                            let id = cx.derive_id(format!(
+                                "variant.{}.field.{}",
+                                variant.name.unwrap(),
+                                field.name.unwrap()
+                            ));
+                            write!(
+                                w,
                                 "<div class=\"sub-variant-field\">\
                                     <span id=\"{id}\" class=\"section-header\">\
                                         <a href=\"#{id}\" class=\"anchor field\">§</a>\
                                         <code>{f}: {t}</code>\
-                                    </span>",
+                                    </span>\
+                                    {doc}\
+                                </div>",
                                 f = field.name.unwrap(),
                                 t = ty.print(cx),
-                            ),
-                        );
-                        write_str(
-                            w,
-                            format_args!(
-                                "{}</div>",
-                                document(cx, field, Some(variant), HeadingOffset::H5),
-                            ),
-                        );
+                                doc = document(cx, field, Some(variant), HeadingOffset::H5),
+                            )?;
+                        }
+                        _ => unreachable!(),
                     }
-                    _ => unreachable!(),
                 }
+                w.write_str("</div>")?;
             }
-            w.push_str("</div>");
         }
-    }
-    write_str(w, format_args!("</div>"));
+        w.write_str("</div>")
+    })
 }
 
-fn item_macro(w: &mut String, cx: &Context<'_>, it: &clean::Item, t: &clean::Macro) {
-    wrap_item(w, |w| {
-        // FIXME: Also print `#[doc(hidden)]` for `macro_rules!` if it `is_doc_hidden`.
-        if !t.macro_rules {
-            write_str(w, format_args!("{}", visibility_print_with_space(it, cx)));
-        }
-        write_str(w, format_args!("{}", Escape(&t.source)));
-    });
-    write_str(w, format_args!("{}", document(cx, it, None, HeadingOffset::H2)));
+fn item_macro(cx: &Context<'_>, it: &clean::Item, t: &clean::Macro) -> impl fmt::Display {
+    fmt::from_fn(|w| {
+        wrap_item(w, |w| {
+            // FIXME: Also print `#[doc(hidden)]` for `macro_rules!` if it `is_doc_hidden`.
+            if !t.macro_rules {
+                write!(w, "{}", visibility_print_with_space(it, cx))?;
+            }
+            write!(w, "{}", Escape(&t.source))
+        })?;
+        write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
+    })
 }
 
-fn item_proc_macro(
-    w: &mut impl fmt::Write,
-    cx: &Context<'_>,
-    it: &clean::Item,
-    m: &clean::ProcMacro,
-) {
-    wrap_item(w, |buffer| {
-        let name = it.name.expect("proc-macros always have names");
-        match m.kind {
-            MacroKind::Bang => {
-                write!(buffer, "{name}!() {{ <span class=\"comment\">/* proc-macro */</span> }}")
-                    .unwrap();
-            }
-            MacroKind::Attr => {
-                write!(buffer, "#[{name}]").unwrap();
-            }
-            MacroKind::Derive => {
-                write!(buffer, "#[derive({name})]").unwrap();
-                if !m.helpers.is_empty() {
-                    buffer
-                        .write_str(
+fn item_proc_macro(cx: &Context<'_>, it: &clean::Item, m: &clean::ProcMacro) -> impl fmt::Display {
+    fmt::from_fn(|w| {
+        wrap_item(w, |w| {
+            let name = it.name.expect("proc-macros always have names");
+            match m.kind {
+                MacroKind::Bang => {
+                    write!(w, "{name}!() {{ <span class=\"comment\">/* proc-macro */</span> }}")?;
+                }
+                MacroKind::Attr => {
+                    write!(w, "#[{name}]")?;
+                }
+                MacroKind::Derive => {
+                    write!(w, "#[derive({name})]")?;
+                    if !m.helpers.is_empty() {
+                        w.write_str(
                             "\n{\n    \
-                        <span class=\"comment\">// Attributes available to this derive:</span>\n",
-                        )
-                        .unwrap();
-                    for attr in &m.helpers {
-                        writeln!(buffer, "    #[{attr}]").unwrap();
+                            <span class=\"comment\">// Attributes available to this derive:</span>\n",
+                        )?;
+                        for attr in &m.helpers {
+                            writeln!(w, "    #[{attr}]")?;
+                        }
+                        w.write_str("}\n")?;
                     }
-                    buffer.write_str("}\n").unwrap();
                 }
             }
-        }
-    });
-    write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap();
+            Ok(())
+        })?;
+        write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
+    })
 }
 
-fn item_primitive(w: &mut impl fmt::Write, cx: &Context<'_>, it: &clean::Item) {
-    let def_id = it.item_id.expect_def_id();
-    write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap();
-    if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) {
-        write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)).unwrap();
-    } else {
-        // We handle the "reference" primitive type on its own because we only want to list
-        // implementations on generic types.
-        let (concrete, synthetic, blanket_impl) = get_filtered_impls_for_reference(&cx.shared, it);
-
-        render_all_impls(w, cx, it, &concrete, &synthetic, &blanket_impl);
-    }
+fn item_primitive(cx: &Context<'_>, it: &clean::Item) -> impl fmt::Display {
+    fmt::from_fn(|w| {
+        let def_id = it.item_id.expect_def_id();
+        write!(w, "{}", document(cx, it, None, HeadingOffset::H2))?;
+        if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) {
+            write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All))?;
+        } else {
+            // We handle the "reference" primitive type on its own because we only want to list
+            // implementations on generic types.
+            let (concrete, synthetic, blanket_impl) =
+                get_filtered_impls_for_reference(&cx.shared, it);
+
+            render_all_impls(w, cx, it, &concrete, &synthetic, &blanket_impl);
+        }
+        Ok(())
+    })
 }
 
 fn item_constant(
-    w: &mut String,
     cx: &Context<'_>,
     it: &clean::Item,
     generics: &clean::Generics,
     ty: &clean::Type,
     c: &clean::ConstantKind,
-) {
-    wrap_item(w, |w| {
-        let tcx = cx.tcx();
-        render_attributes_in_code(w, it, cx);
+) -> impl fmt::Display {
+    fmt::from_fn(|w| {
+        wrap_item(w, |w| {
+            let tcx = cx.tcx();
+            render_attributes_in_code(w, it, cx);
 
-        write_str(
-            w,
-            format_args!(
+            write!(
+                w,
                 "{vis}const {name}{generics}: {typ}{where_clause}",
                 vis = visibility_print_with_space(it, cx),
                 name = it.name.unwrap(),
                 generics = generics.print(cx),
                 typ = ty.print(cx),
-                where_clause = print_where_clause(generics, cx, 0, Ending::NoNewline)
-            ),
-        );
+                where_clause =
+                    print_where_clause(generics, cx, 0, Ending::NoNewline).maybe_display(),
+            )?;
 
-        // FIXME: The code below now prints
-        //            ` = _; // 100i32`
-        //        if the expression is
-        //            `50 + 50`
-        //        which looks just wrong.
-        //        Should we print
-        //            ` = 100i32;`
-        //        instead?
-
-        let value = c.value(tcx);
-        let is_literal = c.is_literal(tcx);
-        let expr = c.expr(tcx);
-        if value.is_some() || is_literal {
-            write_str(w, format_args!(" = {expr};", expr = Escape(&expr)));
-        } else {
-            w.push_str(";");
-        }
+            // FIXME: The code below now prints
+            //            ` = _; // 100i32`
+            //        if the expression is
+            //            `50 + 50`
+            //        which looks just wrong.
+            //        Should we print
+            //            ` = 100i32;`
+            //        instead?
+
+            let value = c.value(tcx);
+            let is_literal = c.is_literal(tcx);
+            let expr = c.expr(tcx);
+            if value.is_some() || is_literal {
+                write!(w, " = {expr};", expr = Escape(&expr))?;
+            } else {
+                w.write_str(";")?;
+            }
 
-        if !is_literal {
-            if let Some(value) = &value {
-                let value_lowercase = value.to_lowercase();
-                let expr_lowercase = expr.to_lowercase();
+            if !is_literal {
+                if let Some(value) = &value {
+                    let value_lowercase = value.to_lowercase();
+                    let expr_lowercase = expr.to_lowercase();
 
-                if value_lowercase != expr_lowercase
-                    && value_lowercase.trim_end_matches("i32") != expr_lowercase
-                {
-                    write_str(w, format_args!(" // {value}", value = Escape(value)));
+                    if value_lowercase != expr_lowercase
+                        && value_lowercase.trim_end_matches("i32") != expr_lowercase
+                    {
+                        write!(w, " // {value}", value = Escape(value))?;
+                    }
                 }
             }
-        }
-    });
+            Ok(())
+        })?;
 
-    write_str(w, format_args!("{}", document(cx, it, None, HeadingOffset::H2)));
+        write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
+    })
 }
 
-fn item_struct(w: &mut String, cx: &Context<'_>, it: &clean::Item, s: &clean::Struct) {
-    wrap_item(w, |w| {
-        render_attributes_in_code(w, it, cx);
-        render_struct(w, it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx);
-    });
-
-    write_str(w, format_args!("{}", document(cx, it, None, HeadingOffset::H2)));
+fn item_struct(cx: &Context<'_>, it: &clean::Item, s: &clean::Struct) -> impl fmt::Display {
+    fmt::from_fn(|w| {
+        wrap_item(w, |w| {
+            render_attributes_in_code(w, it, cx);
+            write!(
+                w,
+                "{}",
+                render_struct(it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx)
+            )
+        })?;
 
-    item_fields(w, cx, it, &s.fields, s.ctor_kind);
+        let def_id = it.item_id.expect_def_id();
 
-    let def_id = it.item_id.expect_def_id();
-    write_str(w, format_args!("{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)));
-    write_str(w, format_args!("{}", document_type_layout(cx, def_id)));
+        write!(
+            w,
+            "{}{}{}{}",
+            document(cx, it, None, HeadingOffset::H2),
+            item_fields(cx, it, &s.fields, s.ctor_kind),
+            render_assoc_items(cx, it, def_id, AssocItemRender::All),
+            document_type_layout(cx, def_id),
+        )
+    })
 }
 
 fn item_fields(
-    w: &mut String,
     cx: &Context<'_>,
     it: &clean::Item,
     fields: &[clean::Item],
     ctor_kind: Option<CtorKind>,
-) {
-    let mut fields = fields
-        .iter()
-        .filter_map(|f| match f.kind {
-            clean::StructFieldItem(ref ty) => Some((f, ty)),
-            _ => None,
-        })
-        .peekable();
-    if let None | Some(CtorKind::Fn) = ctor_kind {
-        if fields.peek().is_some() {
-            let title = format!(
-                "{}{}",
-                if ctor_kind.is_none() { "Fields" } else { "Tuple Fields" },
-                document_non_exhaustive_header(it),
-            );
-            write_section_heading(w, &title, "fields", Some("fields"), document_non_exhaustive(it));
-            for (index, (field, ty)) in fields.enumerate() {
-                let field_name =
-                    field.name.map_or_else(|| index.to_string(), |sym| sym.as_str().to_string());
-                let id = cx.derive_id(format!("{typ}.{field_name}", typ = ItemType::StructField));
-                write_str(
+) -> impl fmt::Display {
+    fmt::from_fn(move |w| {
+        let mut fields = fields
+            .iter()
+            .filter_map(|f| match f.kind {
+                clean::StructFieldItem(ref ty) => Some((f, ty)),
+                _ => None,
+            })
+            .peekable();
+        if let None | Some(CtorKind::Fn) = ctor_kind {
+            if fields.peek().is_some() {
+                let title = format!(
+                    "{}{}",
+                    if ctor_kind.is_none() { "Fields" } else { "Tuple Fields" },
+                    document_non_exhaustive_header(it),
+                );
+                write!(
                     w,
-                    format_args!(
+                    "{}",
+                    write_section_heading(
+                        &title,
+                        "fields",
+                        Some("fields"),
+                        document_non_exhaustive(it)
+                    )
+                )?;
+                for (index, (field, ty)) in fields.enumerate() {
+                    let field_name = field
+                        .name
+                        .map_or_else(|| index.to_string(), |sym| sym.as_str().to_string());
+                    let id =
+                        cx.derive_id(format!("{typ}.{field_name}", typ = ItemType::StructField));
+                    write!(
+                        w,
                         "<span id=\"{id}\" class=\"{item_type} section-header\">\
                             <a href=\"#{id}\" class=\"anchor field\">§</a>\
                             <code>{field_name}: {ty}</code>\
-                        </span>",
+                        </span>\
+                        {doc}",
                         item_type = ItemType::StructField,
-                        ty = ty.print(cx)
-                    ),
-                );
-                write_str(w, format_args!("{}", document(cx, field, Some(it), HeadingOffset::H3)));
+                        ty = ty.print(cx),
+                        doc = document(cx, field, Some(it), HeadingOffset::H3),
+                    )?;
+                }
             }
         }
-    }
+        Ok(())
+    })
 }
 
 fn item_static(
-    w: &mut impl fmt::Write,
     cx: &Context<'_>,
     it: &clean::Item,
     s: &clean::Static,
     safety: Option<hir::Safety>,
-) {
-    wrap_item(w, |buffer| {
-        render_attributes_in_code(buffer, it, cx);
-        write!(
-            buffer,
-            "{vis}{safe}static {mutability}{name}: {typ}",
-            vis = visibility_print_with_space(it, cx),
-            safe = safety.map(|safe| safe.prefix_str()).unwrap_or(""),
-            mutability = s.mutability.print_with_space(),
-            name = it.name.unwrap(),
-            typ = s.type_.print(cx)
-        )
-        .unwrap();
-    });
+) -> impl fmt::Display {
+    fmt::from_fn(move |w| {
+        wrap_item(w, |w| {
+            render_attributes_in_code(w, it, cx);
+            write!(
+                w,
+                "{vis}{safe}static {mutability}{name}: {typ}",
+                vis = visibility_print_with_space(it, cx),
+                safe = safety.map(|safe| safe.prefix_str()).unwrap_or(""),
+                mutability = s.mutability.print_with_space(),
+                name = it.name.unwrap(),
+                typ = s.type_.print(cx)
+            )
+        })?;
 
-    write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap();
+        write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
+    })
 }
 
-fn item_foreign_type(w: &mut impl fmt::Write, cx: &Context<'_>, it: &clean::Item) {
-    wrap_item(w, |buffer| {
-        buffer.write_str("extern {\n").unwrap();
-        render_attributes_in_code(buffer, it, cx);
+fn item_foreign_type(cx: &Context<'_>, it: &clean::Item) -> impl fmt::Display {
+    fmt::from_fn(|w| {
+        wrap_item(w, |w| {
+            w.write_str("extern {\n")?;
+            render_attributes_in_code(w, it, cx);
+            write!(w, "    {}type {};\n}}", visibility_print_with_space(it, cx), it.name.unwrap(),)
+        })?;
+
         write!(
-            buffer,
-            "    {}type {};\n}}",
-            visibility_print_with_space(it, cx),
-            it.name.unwrap(),
+            w,
+            "{}{}",
+            document(cx, it, None, HeadingOffset::H2),
+            render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
         )
-        .unwrap();
-    });
-
-    write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap();
-    write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All))
-        .unwrap();
+    })
 }
 
-fn item_keyword(w: &mut String, cx: &Context<'_>, it: &clean::Item) {
-    write_str(w, format_args!("{}", document(cx, it, None, HeadingOffset::H2)));
+fn item_keyword(cx: &Context<'_>, it: &clean::Item) -> impl fmt::Display {
+    document(cx, it, None, HeadingOffset::H2)
 }
 
 /// Compare two strings treating multi-digit numbers as single units (i.e. natural sort order).
@@ -2111,18 +2185,14 @@ pub(super) fn full_path(cx: &Context<'_>, item: &clean::Item) -> String {
     s
 }
 
-pub(super) fn item_path(ty: ItemType, name: &str) -> impl Display + '_ {
+pub(super) fn item_path(ty: ItemType, name: &str) -> impl Display {
     fmt::from_fn(move |f| match ty {
         ItemType::Module => write!(f, "{}index.html", ensure_trailing_slash(name)),
         _ => write!(f, "{ty}.{name}.html"),
     })
 }
 
-fn bounds<'a, 'tcx>(
-    bounds: &'a [clean::GenericBound],
-    trait_alias: bool,
-    cx: &'a Context<'tcx>,
-) -> impl Display + 'a + Captures<'tcx> {
+fn bounds(bounds: &[clean::GenericBound], trait_alias: bool, cx: &Context<'_>) -> impl Display {
     (!bounds.is_empty())
         .then_some(fmt::from_fn(move |f| {
             let has_lots_of_bounds = bounds.len() > 2;
@@ -2140,14 +2210,15 @@ fn bounds<'a, 'tcx>(
         .maybe_display()
 }
 
-fn wrap_item<W, F>(w: &mut W, f: F)
+fn wrap_item<W, F, T>(w: &mut W, f: F) -> T
 where
     W: fmt::Write,
-    F: FnOnce(&mut W),
+    F: FnOnce(&mut W) -> T,
 {
     write!(w, r#"<pre class="rust item-decl"><code>"#).unwrap();
-    f(w);
+    let res = f(w);
     write!(w, "</code></pre>").unwrap();
+    res
 }
 
 #[derive(PartialEq, Eq)]
@@ -2175,10 +2246,9 @@ fn render_implementor(
     cx: &Context<'_>,
     implementor: &Impl,
     trait_: &clean::Item,
-    w: &mut String,
     implementor_dups: &FxHashMap<Symbol, (DefId, bool)>,
     aliases: &[String],
-) {
+) -> impl fmt::Display {
     // If there's already another implementor that has the same abridged name, use the
     // full path, for example in `std::iter::ExactSizeIterator`
     let use_absolute = match implementor.inner_impl().for_ {
@@ -2191,7 +2261,6 @@ fn render_implementor(
         _ => false,
     };
     render_impl(
-        w,
         cx,
         implementor,
         trait_,
@@ -2205,26 +2274,29 @@ fn render_implementor(
             show_non_assoc_items: false,
             toggle_open_by_default: false,
         },
-    );
+    )
 }
 
-fn render_union<'a, 'cx: 'a>(
-    it: &'a clean::Item,
-    g: Option<&'a clean::Generics>,
-    fields: &'a [clean::Item],
-    cx: &'a Context<'cx>,
-) -> impl Display + 'a + Captures<'cx> {
+fn render_union(
+    it: &clean::Item,
+    g: Option<&clean::Generics>,
+    fields: &[clean::Item],
+    cx: &Context<'_>,
+) -> impl Display {
     fmt::from_fn(move |mut f| {
         write!(f, "{}union {}", visibility_print_with_space(it, cx), it.name.unwrap(),)?;
 
-        let where_displayed = g
-            .map(|g| {
-                let mut buf = g.print(cx).to_string();
-                let where_displayed = print_where_clause_and_check(&mut buf, g, cx);
-                f.write_str(&buf).unwrap();
-                where_displayed
-            })
-            .unwrap_or(false);
+        let where_displayed = if let Some(generics) = g {
+            write!(f, "{}", generics.print(cx))?;
+            if let Some(where_clause) = print_where_clause(generics, cx, 0, Ending::Newline) {
+                write!(f, "{where_clause}")?;
+                true
+            } else {
+                false
+            }
+        } else {
+            false
+        };
 
         // If there wasn't a `where` clause, we add a whitespace.
         if !where_displayed {
@@ -2263,7 +2335,6 @@ fn render_union<'a, 'cx: 'a>(
 }
 
 fn render_struct(
-    w: &mut String,
     it: &clean::Item,
     g: Option<&clean::Generics>,
     ty: Option<CtorKind>,
@@ -2271,33 +2342,35 @@ fn render_struct(
     tab: &str,
     structhead: bool,
     cx: &Context<'_>,
-) {
-    write_str(
-        w,
-        format_args!(
+) -> impl fmt::Display {
+    fmt::from_fn(move |w| {
+        write!(
+            w,
             "{}{}{}",
             visibility_print_with_space(it, cx),
             if structhead { "struct " } else { "" },
             it.name.unwrap()
-        ),
-    );
-    if let Some(g) = g {
-        write_str(w, format_args!("{}", g.print(cx)));
-    }
-    render_struct_fields(
-        w,
-        g,
-        ty,
-        fields,
-        tab,
-        structhead,
-        it.has_stripped_entries().unwrap_or(false),
-        cx,
-    )
+        )?;
+        if let Some(g) = g {
+            write!(w, "{}", g.print(cx))?;
+        }
+        write!(
+            w,
+            "{}",
+            render_struct_fields(
+                g,
+                ty,
+                fields,
+                tab,
+                structhead,
+                it.has_stripped_entries().unwrap_or(false),
+                cx,
+            )
+        )
+    })
 }
 
 fn render_struct_fields(
-    mut w: &mut String,
     g: Option<&clean::Generics>,
     ty: Option<CtorKind>,
     fields: &[clean::Item],
@@ -2305,112 +2378,123 @@ fn render_struct_fields(
     structhead: bool,
     has_stripped_entries: bool,
     cx: &Context<'_>,
-) {
-    match ty {
-        None => {
-            let where_displayed =
-                g.map(|g| print_where_clause_and_check(w, g, cx)).unwrap_or(false);
+) -> impl fmt::Display {
+    fmt::from_fn(move |w| {
+        match ty {
+            None => {
+                let where_displayed = if let Some(generics) = g
+                    && let Some(where_clause) = print_where_clause(generics, cx, 0, Ending::Newline)
+                {
+                    write!(w, "{where_clause}")?;
+                    true
+                } else {
+                    false
+                };
 
-            // If there wasn't a `where` clause, we add a whitespace.
-            if !where_displayed {
-                w.push_str(" {");
-            } else {
-                w.push_str("{");
-            }
-            let count_fields =
-                fields.iter().filter(|f| matches!(f.kind, clean::StructFieldItem(..))).count();
-            let has_visible_fields = count_fields > 0;
-            let toggle = should_hide_fields(count_fields);
-            if toggle {
-                toggle_open(&mut w, format_args!("{count_fields} fields"));
-            }
-            for field in fields {
-                if let clean::StructFieldItem(ref ty) = field.kind {
-                    write_str(
-                        w,
-                        format_args!(
+                // If there wasn't a `where` clause, we add a whitespace.
+                if !where_displayed {
+                    w.write_str(" {")?;
+                } else {
+                    w.write_str("{")?;
+                }
+                let count_fields =
+                    fields.iter().filter(|f| matches!(f.kind, clean::StructFieldItem(..))).count();
+                let has_visible_fields = count_fields > 0;
+                let toggle = should_hide_fields(count_fields);
+                if toggle {
+                    toggle_open(&mut *w, format_args!("{count_fields} fields"));
+                }
+                for field in fields {
+                    if let clean::StructFieldItem(ref ty) = field.kind {
+                        write!(
+                            w,
                             "\n{tab}    {vis}{name}: {ty},",
                             vis = visibility_print_with_space(field, cx),
                             name = field.name.unwrap(),
                             ty = ty.print(cx)
-                        ),
-                    );
+                        )?;
+                    }
                 }
-            }
 
-            if has_visible_fields {
-                if has_stripped_entries {
-                    write_str(
-                        w,
-                        format_args!(
+                if has_visible_fields {
+                    if has_stripped_entries {
+                        write!(
+                            w,
                             "\n{tab}    <span class=\"comment\">/* private fields */</span>"
-                        ),
-                    );
+                        )?;
+                    }
+                    write!(w, "\n{tab}")?;
+                } else if has_stripped_entries {
+                    write!(w, " <span class=\"comment\">/* private fields */</span> ")?;
                 }
-                write_str(w, format_args!("\n{tab}"));
-            } else if has_stripped_entries {
-                write_str(w, format_args!(" <span class=\"comment\">/* private fields */</span> "));
-            }
-            if toggle {
-                toggle_close(&mut w);
+                if toggle {
+                    toggle_close(&mut *w);
+                }
+                w.write_str("}")?;
             }
-            w.push_str("}");
-        }
-        Some(CtorKind::Fn) => {
-            w.push_str("(");
-            if !fields.is_empty()
-                && fields.iter().all(|field| {
-                    matches!(field.kind, clean::StrippedItem(box clean::StructFieldItem(..)))
-                })
-            {
-                write_str(w, format_args!("<span class=\"comment\">/* private fields */</span>"));
-            } else {
-                for (i, field) in fields.iter().enumerate() {
-                    if i > 0 {
-                        w.push_str(", ");
-                    }
-                    match field.kind {
-                        clean::StrippedItem(box clean::StructFieldItem(..)) => {
-                            write_str(w, format_args!("_"));
+            Some(CtorKind::Fn) => {
+                w.write_str("(")?;
+                if !fields.is_empty()
+                    && fields.iter().all(|field| {
+                        matches!(field.kind, clean::StrippedItem(box clean::StructFieldItem(..)))
+                    })
+                {
+                    write!(w, "<span class=\"comment\">/* private fields */</span>")?;
+                } else {
+                    for (i, field) in fields.iter().enumerate() {
+                        if i > 0 {
+                            w.write_str(", ")?;
                         }
-                        clean::StructFieldItem(ref ty) => {
-                            write_str(
-                                w,
-                                format_args!(
+                        match field.kind {
+                            clean::StrippedItem(box clean::StructFieldItem(..)) => {
+                                write!(w, "_")?;
+                            }
+                            clean::StructFieldItem(ref ty) => {
+                                write!(
+                                    w,
                                     "{}{}",
                                     visibility_print_with_space(field, cx),
                                     ty.print(cx)
-                                ),
-                            );
+                                )?;
+                            }
+                            _ => unreachable!(),
                         }
-                        _ => unreachable!(),
                     }
                 }
+                w.write_str(")")?;
+                if let Some(g) = g {
+                    write!(
+                        w,
+                        "{}",
+                        print_where_clause(g, cx, 0, Ending::NoNewline).maybe_display()
+                    )?;
+                }
+                // We only want a ";" when we are displaying a tuple struct, not a variant tuple struct.
+                if structhead {
+                    w.write_str(";")?;
+                }
             }
-            w.push_str(")");
-            if let Some(g) = g {
-                write_str(w, format_args!("{}", print_where_clause(g, cx, 0, Ending::NoNewline)));
-            }
-            // We only want a ";" when we are displaying a tuple struct, not a variant tuple struct.
-            if structhead {
-                w.push_str(";");
-            }
-        }
-        Some(CtorKind::Const) => {
-            // Needed for PhantomData.
-            if let Some(g) = g {
-                write_str(w, format_args!("{}", print_where_clause(g, cx, 0, Ending::NoNewline)));
+            Some(CtorKind::Const) => {
+                // Needed for PhantomData.
+                if let Some(g) = g {
+                    write!(
+                        w,
+                        "{}",
+                        print_where_clause(g, cx, 0, Ending::NoNewline).maybe_display()
+                    )?;
+                }
+                w.write_str(";")?;
             }
-            w.push_str(";");
         }
-    }
+        Ok(())
+    })
 }
 
 fn document_non_exhaustive_header(item: &clean::Item) -> &str {
     if item.is_non_exhaustive() { " (Non-exhaustive)" } else { "" }
 }
 
-fn document_non_exhaustive(item: &clean::Item) -> impl Display + '_ {
+fn document_non_exhaustive(item: &clean::Item) -> impl Display {
     fmt::from_fn(|f| {
         if item.is_non_exhaustive() {
             write!(
diff --git a/src/librustdoc/html/render/type_layout.rs b/src/librustdoc/html/render/type_layout.rs
index 0f01db5f6bc..a1ee5c8c548 100644
--- a/src/librustdoc/html/render/type_layout.rs
+++ b/src/librustdoc/html/render/type_layout.rs
@@ -2,7 +2,6 @@ use std::fmt;
 
 use rinja::Template;
 use rustc_abi::{Primitive, TagEncoding, Variants};
-use rustc_data_structures::captures::Captures;
 use rustc_hir::def_id::DefId;
 use rustc_middle::span_bug;
 use rustc_middle::ty::layout::LayoutError;
@@ -26,10 +25,7 @@ struct TypeLayoutSize {
     size: u64,
 }
 
-pub(crate) fn document_type_layout<'a, 'cx: 'a>(
-    cx: &'a Context<'cx>,
-    ty_def_id: DefId,
-) -> impl fmt::Display + 'a + Captures<'cx> {
+pub(crate) fn document_type_layout(cx: &Context<'_>, ty_def_id: DefId) -> impl fmt::Display {
     fmt::from_fn(move |f| {
         if !cx.shared.show_type_layout {
             return Ok(());
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index a4dec013fc0..b2bbf4614bf 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -153,7 +153,7 @@ fn write_rendered_cross_crate_info(
     include_sources: bool,
 ) -> Result<(), Error> {
     let m = &opt.should_merge;
-    if opt.emit.is_empty() || opt.emit.contains(&EmitType::InvocationSpecific) {
+    if opt.should_emit_crate() {
         if include_sources {
             write_rendered_cci::<SourcesPart, _>(SourcesPart::blank, dst, crates, m)?;
         }
@@ -636,26 +636,22 @@ impl TypeAliasPart {
                         } else {
                             AssocItemLink::Anchor(None)
                         };
-                        let text = {
-                            let mut buf = String::new();
-                            super::render_impl(
-                                &mut buf,
-                                cx,
-                                impl_,
-                                type_alias_item,
-                                assoc_link,
-                                RenderMode::Normal,
-                                None,
-                                &[],
-                                ImplRenderingParameters {
-                                    show_def_docs: true,
-                                    show_default_items: true,
-                                    show_non_assoc_items: true,
-                                    toggle_open_by_default: true,
-                                },
-                            );
-                            buf
-                        };
+                        let text = super::render_impl(
+                            cx,
+                            impl_,
+                            type_alias_item,
+                            assoc_link,
+                            RenderMode::Normal,
+                            None,
+                            &[],
+                            ImplRenderingParameters {
+                                show_def_docs: true,
+                                show_default_items: true,
+                                show_non_assoc_items: true,
+                                toggle_open_by_default: true,
+                            },
+                        )
+                        .to_string();
                         let type_alias_fqp = (*type_alias_fqp).iter().join("::");
                         if Some(&text) == ret.last().map(|s: &AliasSerializableImpl| &s.text) {
                             ret.last_mut()
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index 78c86a27632..cbbd4b01d83 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -333,7 +333,7 @@ pub(crate) fn print_src(
     source_context: &SourceContext<'_>,
 ) {
     let mut lines = s.lines().count();
-    let line_info = if let SourceContext::Embedded(ref info) = source_context {
+    let line_info = if let SourceContext::Embedded(info) = source_context {
         highlight::LineInfo::new_scraped(lines as u32, info.offset as u32)
     } else {
         highlight::LineInfo::new(lines as u32)
diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts
index acea7828e86..1554c045a32 100644
--- a/src/librustdoc/html/static/js/rustdoc.d.ts
+++ b/src/librustdoc/html/static/js/rustdoc.d.ts
@@ -123,7 +123,7 @@ declare namespace rustdoc {
      * Same as QueryElement, but bindings and typeFilter support strings
      */
     interface ParserQueryElement {
-        name: string,
+        name: string|null,
         id: number|null,
         fullPath: Array<string>,
         pathWithoutLast: Array<string>,
@@ -131,11 +131,17 @@ declare namespace rustdoc {
         normalizedPathLast: string,
         generics: Array<ParserQueryElement>,
         bindings: Map<string, Array<ParserQueryElement>>,
-        bindingName: {name: string, generics: ParserQueryElement[]}|null,
-        typeFilter: string|null,
+        bindingName: {name: string|null, generics: ParserQueryElement[]}|null,
+        typeFilter: number|string|null,
     }
 
     /**
+     * Same as ParserQueryElement, but all fields are optional.
+     */
+    type ParserQueryElementFields = {
+        [K in keyof ParserQueryElement]?: ParserQueryElement[T]
+    }
+    /**
      * Intermediate parser state. Discarded when parsing is done.
      */
     interface ParserState {
@@ -176,10 +182,11 @@ declare namespace rustdoc {
         name: string,
         normalizedName: string,
         word: string,
+        paramNames: string[],
         parent: ({ty: number, name: string, path: string, exactPath: string}|null|undefined),
         path: string,
         ty: number,
-        type?: FunctionSearchType
+        type: FunctionSearchType | null,
     }
 
     /**
@@ -390,7 +397,7 @@ declare namespace rustdoc {
      */
     type RawSearchIndexCrate = {
     doc: string,
-    a: Object,
+    a: { [key: string]: number[] },
     n: Array<string>,
     t: string,
     D: string,
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index ccbd6811b07..c275127997a 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -638,7 +638,6 @@ function getNextElem(query, parserState, elems, isInGenerics) {
                 getFilteredNextElem(query, parserState, generics, isInGenerics);
                 generics[generics.length - 1].bindingName = makePrimitiveElement("output");
             } else {
-                // @ts-expect-error
                 generics.push(makePrimitiveElement(null, {
                     bindingName: makePrimitiveElement("output"),
                     typeFilter: null,
@@ -791,7 +790,7 @@ function createQueryElement(query, parserState, name, generics, isInGenerics) {
         generics: generics.filter(gen => {
             // Syntactically, bindings are parsed as generics,
             // but the query engine treats them differently.
-            if (gen.bindingName !== null) {
+            if (gen.bindingName !== null && gen.bindingName.name !== null) {
                 if (gen.name !== null) {
                     gen.bindingName.generics.unshift(gen);
                 }
@@ -811,8 +810,8 @@ function createQueryElement(query, parserState, name, generics, isInGenerics) {
 
 /**
  *
- * @param {string} name
- * @param {Object=} extra
+ * @param {string|null} name
+ * @param {rustdoc.ParserQueryElementFields=} extra
  * @returns {rustdoc.ParserQueryElement}
  */
 function makePrimitiveElement(name, extra) {
@@ -1478,73 +1477,61 @@ class DocSearch {
          * Special type name IDs for searching by array.
          * @type {number}
          */
-        // @ts-expect-error
         this.typeNameIdOfArray = this.buildTypeMapIndex("array");
         /**
          * Special type name IDs for searching by slice.
          * @type {number}
          */
-        // @ts-expect-error
         this.typeNameIdOfSlice = this.buildTypeMapIndex("slice");
         /**
          * Special type name IDs for searching by both array and slice (`[]` syntax).
          * @type {number}
          */
-        // @ts-expect-error
         this.typeNameIdOfArrayOrSlice = this.buildTypeMapIndex("[]");
         /**
          * Special type name IDs for searching by tuple.
          * @type {number}
          */
-        // @ts-expect-error
         this.typeNameIdOfTuple = this.buildTypeMapIndex("tuple");
         /**
          * Special type name IDs for searching by unit.
          * @type {number}
          */
-        // @ts-expect-error
         this.typeNameIdOfUnit = this.buildTypeMapIndex("unit");
         /**
          * Special type name IDs for searching by both tuple and unit (`()` syntax).
          * @type {number}
          */
-        // @ts-expect-error
         this.typeNameIdOfTupleOrUnit = this.buildTypeMapIndex("()");
         /**
          * Special type name IDs for searching `fn`.
          * @type {number}
          */
-        // @ts-expect-error
         this.typeNameIdOfFn = this.buildTypeMapIndex("fn");
         /**
          * Special type name IDs for searching `fnmut`.
          * @type {number}
          */
-        // @ts-expect-error
         this.typeNameIdOfFnMut = this.buildTypeMapIndex("fnmut");
         /**
          * Special type name IDs for searching `fnonce`.
          * @type {number}
          */
-        // @ts-expect-error
         this.typeNameIdOfFnOnce = this.buildTypeMapIndex("fnonce");
         /**
          * Special type name IDs for searching higher order functions (`->` syntax).
          * @type {number}
          */
-        // @ts-expect-error
         this.typeNameIdOfHof = this.buildTypeMapIndex("->");
         /**
          * Special type name IDs the output assoc type.
          * @type {number}
          */
-        // @ts-expect-error
         this.typeNameIdOfOutput = this.buildTypeMapIndex("output", true);
         /**
          * Special type name IDs for searching by reference.
          * @type {number}
          */
-        // @ts-expect-error
         this.typeNameIdOfReference = this.buildTypeMapIndex("reference");
 
         /**
@@ -1586,7 +1573,6 @@ class DocSearch {
         /**
          *  @type {Array<rustdoc.Row>}
          */
-        // @ts-expect-error
         this.searchIndex = this.buildIndex(rawSearchIndex);
     }
 
@@ -1598,10 +1584,16 @@ class DocSearch {
      * done more quickly. Two types with the same name but different item kinds
      * get the same ID.
      *
-     * @param {string} name
+     * @template T extends string
+     * @overload
+     * @param {T} name
      * @param {boolean=} isAssocType - True if this is an assoc type
+     * @returns {T extends "" ? null : number}
+     *
+     * @param {string} name
+     * @param {boolean=} isAssocType
+     * @returns {number | null}
      *
-     * @returns {number?}
      */
     buildTypeMapIndex(name, isAssocType) {
         if (name === "" || name === null) {
@@ -1909,6 +1901,7 @@ class DocSearch {
      * Convert raw search index into in-memory search index.
      *
      * @param {Map<string, rustdoc.RawSearchIndexCrate>} rawSearchIndex
+     * @returns {rustdoc.Row[]}
      */
     buildIndex(rawSearchIndex) {
         /**
@@ -2008,6 +2001,7 @@ class DocSearch {
             return cb;
         };
 
+        /** @type {rustdoc.Row[]} */
         const searchIndex = [];
         let currentIndex = 0;
         let id = 0;
@@ -2108,8 +2102,6 @@ class DocSearch {
             // an array of [(Number) item type,
             //              (String) name]
             const rawPaths = crateCorpus.p;
-            // an array of [(String) alias name
-            //             [Number] index to items]
             const aliases = crateCorpus.a;
             // an array of [(Number) item index,
             //              (String) comma-separated list of function generic param names]
@@ -2232,6 +2224,7 @@ class DocSearch {
                 // object defined above.
                 const itemParentIdx = itemParentIdxDecoder.next();
                 normalizedName = word.indexOf("_") === -1 ? word : word.replace(/_/g, "");
+                /** @type {rustdoc.Row} */
                 const row = {
                     crate,
                     ty: itemTypes.charCodeAt(i) - 65, // 65 = "A"
@@ -2274,16 +2267,14 @@ class DocSearch {
                         continue;
                     }
 
-                    // @ts-expect-error
+                    /** @type{number[]} */
                     let currentNameAliases;
                     if (currentCrateAliases.has(alias_name)) {
                         currentNameAliases = currentCrateAliases.get(alias_name);
                     } else {
                         currentNameAliases = [];
-                        // @ts-expect-error
                         currentCrateAliases.set(alias_name, currentNameAliases);
                     }
-                    // @ts-expect-error
                     for (const local_alias of aliases[alias_name]) {
                         currentNameAliases.push(local_alias + currentIndex);
                     }
@@ -2326,15 +2317,13 @@ class DocSearch {
          * @param {rustdoc.ParserQueryElement} elem
          */
         function convertTypeFilterOnElem(elem) {
-            if (elem.typeFilter !== null) {
+            if (typeof elem.typeFilter === "string") {
                 let typeFilter = elem.typeFilter;
                 if (typeFilter === "const") {
                     typeFilter = "constant";
                 }
-                // @ts-expect-error
                 elem.typeFilter = itemTypeFromName(typeFilter);
             } else {
-                // @ts-expect-error
                 elem.typeFilter = NO_TYPE_FILTER;
             }
             for (const elem2 of elem.generics) {
@@ -2407,9 +2396,9 @@ class DocSearch {
                     continue;
                 }
                 if (!foundStopChar) {
-                    let extra = "";
+                    /** @type String[] */
+                    let extra = [];
                     if (isLastElemGeneric(query.elems, parserState)) {
-                        // @ts-expect-error
                         extra = [" after ", ">"];
                     } else if (prevIs(parserState, "\"")) {
                         throw ["Cannot have more than one element if you use quotes"];
@@ -2547,7 +2536,7 @@ class DocSearch {
          * See `buildTypeMapIndex` for more information.
          *
          * @param {rustdoc.QueryElement} elem
-         * @param {boolean} isAssocType
+         * @param {boolean=} isAssocType
          */
         const convertNameToId = (elem, isAssocType) => {
             const loweredName = elem.pathLast.toLowerCase();
@@ -2627,7 +2616,6 @@ class DocSearch {
                 ];
             }
             for (const elem2 of elem.generics) {
-                // @ts-expect-error
                 convertNameToId(elem2);
             }
             elem.bindings = new Map(Array.from(elem.bindings.entries())
@@ -2750,7 +2738,11 @@ class DocSearch {
             return [displayPath, href, `${exactPath}::${name}`];
         };
 
-        // @ts-expect-error
+        /**
+         *
+         * @param {string} path
+         * @returns {string}
+         */
         function pathSplitter(path) {
             const tmp = "<span>" + path.replace(/::/g, "::</span><span>");
             if (tmp.endsWith("<span>")) {
@@ -2763,9 +2755,9 @@ class DocSearch {
          * Add extra data to result objects, and filter items that have been
          * marked for removal.
          *
-         * @param {[rustdoc.ResultObject]} results
+         * @param {rustdoc.ResultObject[]} results
          * @param {"sig"|"elems"|"returned"|null} typeInfo
-         * @returns {[rustdoc.ResultObject]}
+         * @returns {rustdoc.ResultObject[]}
          */
         const transformResults = (results, typeInfo) => {
             const duplicates = new Set();
@@ -2840,7 +2832,7 @@ class DocSearch {
             }
             let fnInputs = null;
             let fnOutput = null;
-            // @ts-expect-error
+            /** @type {Map<number, number> | null} */
             let mgens = null;
             if (typeInfo !== "elems" && typeInfo !== "returned") {
                 fnInputs = unifyFunctionTypes(
@@ -3053,7 +3045,6 @@ class DocSearch {
                             writeFn(nested, result);
                         }
                         return;
-                    // @ts-expect-error
                     } else if (mgens) {
                         for (const [queryId, fnId] of mgens) {
                             if (fnId === fnType.id) {
@@ -3069,7 +3060,7 @@ class DocSearch {
                         name: fnParamNames[-1 - fnType.id],
                         highlighted: !!fnType.highlighted,
                     }, result);
-                    // @ts-expect-error
+                    /** @type{string[]} */
                     const where = [];
                     onEachBtwn(
                         fnType.generics,
@@ -3079,7 +3070,6 @@ class DocSearch {
                         () => pushText({ name: " + ", highlighted: false }, where),
                     );
                     if (where.length > 0) {
-                        // @ts-expect-error
                         whereClause.set(fnParamNames[-1 - fnType.id], where);
                     }
                 } else {
@@ -3181,7 +3171,7 @@ class DocSearch {
          * @param {rustdoc.Results} results
          * @param {"sig"|"elems"|"returned"|null} typeInfo
          * @param {string} preferredCrate
-         * @returns {Promise<[rustdoc.ResultObject]>}
+         * @returns {Promise<rustdoc.ResultObject[]>}
          */
         const sortResults = async(results, typeInfo, preferredCrate) => {
             const userQuery = parsedQuery.userQuery;
@@ -3337,7 +3327,6 @@ class DocSearch {
                 return 0;
             });
 
-            // @ts-expect-error
             return transformResults(result_list, typeInfo);
         };
 
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 1f2f8f7d33a..4fe5e13c3af 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -147,7 +147,7 @@ pub fn main() {
 
         #[cfg(target_os = "macos")]
         {
-            extern "C" {
+            unsafe extern "C" {
                 fn _rjem_je_zone_register();
             }
 
@@ -561,7 +561,7 @@ fn opts() -> Vec<RustcOptGroup> {
             "",
             "emit",
             "Comma separated list of types of output for rustdoc to emit",
-            "[unversioned-shared-resources,toolchain-shared-resources,invocation-specific]",
+            "[unversioned-shared-resources,toolchain-shared-resources,invocation-specific,dep-info]",
         ),
         opt(Unstable, FlagMulti, "", "no-run", "Compile doctests without running them", ""),
         opt(
@@ -890,7 +890,13 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) {
                 // if we ran coverage, bail early, we don't need to also generate docs at this point
                 // (also we didn't load in any of the useful passes)
                 return;
-            } else if run_check {
+            }
+
+            if render_opts.dep_info().is_some() {
+                rustc_interface::passes::write_dep_info(tcx);
+            }
+
+            if run_check {
                 // Since we're in "check" mode, no need to generate anything beyond this point.
                 return;
             }
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 97e6d314642..440d6331457 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -58,7 +58,7 @@ fn filter_assoc_items_by_name_and_namespace(
     assoc_items_of: DefId,
     ident: Ident,
     ns: Namespace,
-) -> impl Iterator<Item = &ty::AssocItem> + '_ {
+) -> impl Iterator<Item = &ty::AssocItem> {
     tcx.associated_items(assoc_items_of).filter_by_name_unhygienic(ident.name).filter(move |item| {
         item.kind.namespace() == ns && tcx.hygienic_eq(ident, item.ident(tcx), assoc_items_of)
     })
diff --git a/src/llvm-project b/src/llvm-project
-Subproject 92e80685d0d5dcea3ccf321995c43b72338639c
+Subproject 1c3bb96fdb6db7b8e8f24edb016099c223fdd27
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
index ab5f97199ce..4f024ecaf29 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
@@ -682,19 +682,20 @@ pub fn eq_generics(l: &Generics, r: &Generics) -> bool {
 
 pub fn eq_where_predicate(l: &WherePredicate, r: &WherePredicate) -> bool {
     use WherePredicateKind::*;
-    match (&l.kind, &r.kind) {
-        (BoundPredicate(l), BoundPredicate(r)) => {
-            over(&l.bound_generic_params, &r.bound_generic_params, |l, r| {
-                eq_generic_param(l, r)
-            }) && eq_ty(&l.bounded_ty, &r.bounded_ty)
-                && over(&l.bounds, &r.bounds, eq_generic_bound)
-        },
-        (RegionPredicate(l), RegionPredicate(r)) => {
-            eq_id(l.lifetime.ident, r.lifetime.ident) && over(&l.bounds, &r.bounds, eq_generic_bound)
-        },
-        (EqPredicate(l), EqPredicate(r)) => eq_ty(&l.lhs_ty, &r.lhs_ty) && eq_ty(&l.rhs_ty, &r.rhs_ty),
-        _ => false,
-    }
+    over(&l.attrs, &r.attrs, eq_attr) 
+        && match (&l.kind, &r.kind) {
+            (BoundPredicate(l), BoundPredicate(r)) => {
+                over(&l.bound_generic_params, &r.bound_generic_params, |l, r| {
+                    eq_generic_param(l, r)
+                }) && eq_ty(&l.bounded_ty, &r.bounded_ty)
+                    && over(&l.bounds, &r.bounds, eq_generic_bound)
+            },
+            (RegionPredicate(l), RegionPredicate(r)) => {
+                eq_id(l.lifetime.ident, r.lifetime.ident) && over(&l.bounds, &r.bounds, eq_generic_bound)
+            },
+            (EqPredicate(l), EqPredicate(r)) => eq_ty(&l.lhs_ty, &r.lhs_ty) && eq_ty(&l.rhs_ty, &r.rhs_ty),
+            _ => false,
+        }
 }
 
 pub fn eq_use_tree(l: &UseTree, r: &UseTree) -> bool {
diff --git a/src/tools/clippy/clippy_utils/src/macros.rs b/src/tools/clippy/clippy_utils/src/macros.rs
index 3ce2cdfebe9..1a457bc7f21 100644
--- a/src/tools/clippy/clippy_utils/src/macros.rs
+++ b/src/tools/clippy/clippy_utils/src/macros.rs
@@ -1,6 +1,6 @@
 #![allow(clippy::similar_names)] // `expr` and `expn`
 
-use std::sync::Arc;
+use std::sync::{Arc, OnceLock};
 
 use crate::get_unique_attr;
 use crate::visitors::{Descend, for_each_expr_without_closures};
@@ -8,7 +8,6 @@ use crate::visitors::{Descend, for_each_expr_without_closures};
 use arrayvec::ArrayVec;
 use rustc_ast::{FormatArgs, FormatArgument, FormatPlaceholder};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::OnceLock;
 use rustc_hir::{self as hir, Expr, ExprKind, HirId, Node, QPath};
 use rustc_lint::{LateContext, LintContext};
 use rustc_span::def_id::DefId;
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index b302c6a49f5..978836cb663 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -190,6 +190,9 @@ pub struct Config {
     /// The cargo executable.
     pub cargo_path: Option<PathBuf>,
 
+    /// Rustc executable used to compile run-make recipes.
+    pub stage0_rustc_path: Option<PathBuf>,
+
     /// The rustdoc executable.
     pub rustdoc_path: Option<PathBuf>,
 
diff --git a/src/tools/compiletest/src/directive-list.rs b/src/tools/compiletest/src/directive-list.rs
index 8c909bcb195..b2ad5a3b3d0 100644
--- a/src/tools/compiletest/src/directive-list.rs
+++ b/src/tools/compiletest/src/directive-list.rs
@@ -52,6 +52,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "ignore-coverage-run",
     "ignore-cross-compile",
     "ignore-eabi",
+    "ignore-elf",
     "ignore-emscripten",
     "ignore-endian-big",
     "ignore-enzyme",
@@ -182,6 +183,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "only-bpf",
     "only-cdb",
     "only-dist",
+    "only-elf",
     "only-emscripten",
     "only-gnu",
     "only-i686-pc-windows-gnu",
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 53ee901b8bc..7675e13990d 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -709,11 +709,11 @@ impl TestProps {
 /// returns a struct containing various parts of the directive.
 fn line_directive<'line>(
     line_number: usize,
-    comment: &str,
     original_line: &'line str,
 ) -> Option<DirectiveLine<'line>> {
     // Ignore lines that don't start with the comment prefix.
-    let after_comment = original_line.trim_start().strip_prefix(comment)?.trim_start();
+    let after_comment =
+        original_line.trim_start().strip_prefix(COMPILETEST_DIRECTIVE_PREFIX)?.trim_start();
 
     let revision;
     let raw_directive;
@@ -722,7 +722,7 @@ fn line_directive<'line>(
         // A comment like `//@[foo]` only applies to revision `foo`.
         let Some((line_revision, after_close_bracket)) = after_open_bracket.split_once(']') else {
             panic!(
-                "malformed condition directive: expected `{comment}[foo]`, found `{original_line}`"
+                "malformed condition directive: expected `{COMPILETEST_DIRECTIVE_PREFIX}[foo]`, found `{original_line}`"
             )
         };
 
@@ -836,6 +836,8 @@ pub(crate) fn check_directive<'a>(
     CheckDirectiveResult { is_known_directive: is_known(&directive_name), trailing_directive }
 }
 
+const COMPILETEST_DIRECTIVE_PREFIX: &str = "//@";
+
 fn iter_header(
     mode: Mode,
     _suite: &str,
@@ -849,8 +851,7 @@ fn iter_header(
     }
 
     // Coverage tests in coverage-run mode always have these extra directives, without needing to
-    // specify them manually in every test file. (Some of the comments below have been copied over
-    // from the old `tests/run-make/coverage-reports/Makefile`, which no longer exists.)
+    // specify them manually in every test file.
     //
     // FIXME(jieyouxu): I feel like there's a better way to do this, leaving for later.
     if mode == Mode::CoverageRun {
@@ -867,9 +868,6 @@ fn iter_header(
         }
     }
 
-    // NOTE(jieyouxu): once we get rid of `Makefile`s we can unconditionally check for `//@`.
-    let comment = if testfile.extension().is_some_and(|e| e == "rs") { "//@" } else { "#" };
-
     let mut rdr = BufReader::with_capacity(1024, rdr);
     let mut ln = String::new();
     let mut line_number = 0;
@@ -882,7 +880,7 @@ fn iter_header(
         }
         let ln = ln.trim();
 
-        let Some(directive_line) = line_directive(line_number, comment, ln) else {
+        let Some(directive_line) = line_directive(line_number, ln) else {
             continue;
         };
 
diff --git a/src/tools/compiletest/src/header/cfg.rs b/src/tools/compiletest/src/header/cfg.rs
index 72a3b9d85c8..c369fff97f4 100644
--- a/src/tools/compiletest/src/header/cfg.rs
+++ b/src/tools/compiletest/src/header/cfg.rs
@@ -167,6 +167,16 @@ fn parse_cfg_name_directive<'a>(
     }
 
     condition! {
+        name: "elf",
+        condition: !config.target.contains("windows")
+            && !config.target.contains("wasm")
+            && !config.target.contains("apple")
+            && !config.target.contains("aix")
+            && !config.target.contains("uefi"),
+        message: "when the target binary format is ELF"
+    }
+
+    condition! {
         name: "enzyme",
         condition: config.has_enzyme,
         message: "when rustc is built with LLVM Enzyme"
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index d7079fdeee6..007318be7cc 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -239,11 +239,6 @@ fn check_ignore(config: &Config, contents: &str) -> bool {
     d.ignore
 }
 
-fn parse_makefile(config: &Config, contents: &str) -> EarlyProps {
-    let bytes = contents.as_bytes();
-    EarlyProps::from_reader(config, Path::new("Makefile"), bytes)
-}
-
 #[test]
 fn should_fail() {
     let config: Config = cfg().build();
@@ -261,10 +256,6 @@ fn revisions() {
     let config: Config = cfg().build();
 
     assert_eq!(parse_rs(&config, "//@ revisions: a b c").revisions, vec!["a", "b", "c"],);
-    assert_eq!(
-        parse_makefile(&config, "# revisions: hello there").revisions,
-        vec!["hello", "there"],
-    );
 }
 
 #[test]
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index 9dff7047bc4..dd611b19a8d 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -21,7 +21,7 @@ pub mod util;
 
 use core::panic;
 use std::collections::HashSet;
-use std::ffi::{OsStr, OsString};
+use std::ffi::OsString;
 use std::io::{self, ErrorKind};
 use std::path::{Path, PathBuf};
 use std::process::{Command, Stdio};
@@ -54,6 +54,12 @@ pub fn parse_config(args: Vec<String>) -> Config {
         .reqopt("", "run-lib-path", "path to target shared libraries", "PATH")
         .reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH")
         .optopt("", "cargo-path", "path to cargo to use for compiling", "PATH")
+        .optopt(
+            "",
+            "stage0-rustc-path",
+            "path to rustc to use for compiling run-make recipes",
+            "PATH",
+        )
         .optopt("", "rustdoc-path", "path to rustdoc to use for compiling", "PATH")
         .optopt("", "coverage-dump-path", "path to coverage-dump to use in tests", "PATH")
         .reqopt("", "python", "path to python to use for doc tests", "PATH")
@@ -268,12 +274,8 @@ pub fn parse_config(args: Vec<String>) -> Config {
                 let path = Path::new(f);
                 let mut iter = path.iter().skip(1);
 
-                // We skip the test folder and check if the user passed `rmake.rs` or `Makefile`.
-                if iter
-                    .next()
-                    .is_some_and(|s| s == OsStr::new("rmake.rs") || s == OsStr::new("Makefile"))
-                    && iter.next().is_none()
-                {
+                // We skip the test folder and check if the user passed `rmake.rs`.
+                if iter.next().is_some_and(|s| s == "rmake.rs") && iter.next().is_none() {
                     path.parent().unwrap().to_str().unwrap().to_string()
                 } else {
                     f.to_string()
@@ -320,6 +322,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
         run_lib_path: make_absolute(opt_path(matches, "run-lib-path")),
         rustc_path: opt_path(matches, "rustc-path"),
         cargo_path: matches.opt_str("cargo-path").map(PathBuf::from),
+        stage0_rustc_path: matches.opt_str("stage0-rustc-path").map(PathBuf::from),
         rustdoc_path: matches.opt_str("rustdoc-path").map(PathBuf::from),
         coverage_dump_path: matches.opt_str("coverage-dump-path").map(PathBuf::from),
         python: matches.opt_str("python").unwrap(),
@@ -776,16 +779,9 @@ fn collect_tests_from_dir(
         return Ok(());
     }
 
-    // For run-make tests, a "test file" is actually a directory that contains
-    // an `rmake.rs` or `Makefile`"
+    // For run-make tests, a "test file" is actually a directory that contains an `rmake.rs`.
     if cx.config.mode == Mode::RunMake {
-        if dir.join("Makefile").exists() && dir.join("rmake.rs").exists() {
-            return Err(io::Error::other(
-                "run-make tests cannot have both `Makefile` and `rmake.rs`",
-            ));
-        }
-
-        if dir.join("Makefile").exists() || dir.join("rmake.rs").exists() {
+        if dir.join("rmake.rs").exists() {
             let paths = TestPaths {
                 file: dir.to_path_buf(),
                 relative_dir: relative_dir_path.parent().unwrap().to_path_buf(),
@@ -854,24 +850,14 @@ pub fn is_test(file_name: &OsString) -> bool {
     !invalid_prefixes.iter().any(|p| file_name.starts_with(p))
 }
 
-/// For a single test file, creates one or more test structures (one per revision)
-/// that can be handed over to libtest to run, possibly in parallel.
+/// For a single test file, creates one or more test structures (one per revision) that can be
+/// handed over to libtest to run, possibly in parallel.
 fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &TestPaths) {
-    // For run-make tests, each "test file" is actually a _directory_ containing
-    // an `rmake.rs` or `Makefile`. But for the purposes of directive parsing,
-    // we want to look at that recipe file, not the directory itself.
+    // For run-make tests, each "test file" is actually a _directory_ containing an `rmake.rs`. But
+    // for the purposes of directive parsing, we want to look at that recipe file, not the directory
+    // itself.
     let test_path = if cx.config.mode == Mode::RunMake {
-        if testpaths.file.join("rmake.rs").exists() && testpaths.file.join("Makefile").exists() {
-            panic!("run-make tests cannot have both `rmake.rs` and `Makefile`");
-        }
-
-        if testpaths.file.join("rmake.rs").exists() {
-            // Parse directives in rmake.rs.
-            testpaths.file.join("rmake.rs")
-        } else {
-            // Parse directives in the Makefile.
-            testpaths.file.join("Makefile")
-        }
+        testpaths.file.join("rmake.rs")
     } else {
         PathBuf::from(&testpaths.file)
     };
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index f36d43b211f..6e250ca12c9 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -2412,8 +2412,9 @@ impl<'test> TestCx<'test> {
         let rust_src_dir = rust_src_dir.read_link().unwrap_or(rust_src_dir.to_path_buf());
         normalize_path(&rust_src_dir.join("library"), "$SRC_DIR_REAL");
 
-        // eg. /home/user/rust/build/x86_64-unknown-linux-gnu/test/ui
-        normalize_path(&self.config.build_test_suite_root, "$TEST_BUILD_DIR");
+        // eg.
+        // /home/user/rust/build/x86_64-unknown-linux-gnu/test/ui/<test_dir>/$name.$revision.$mode/
+        normalize_path(&self.output_base_dir(), "$TEST_BUILD_DIR");
         // eg. /home/user/rust/build
         normalize_path(&self.config.build_root, "$BUILD_DIR");
 
@@ -2434,6 +2435,18 @@ impl<'test> TestCx<'test> {
             .into_owned();
 
         normalized = Self::normalize_platform_differences(&normalized);
+
+        // Normalize long type name hash.
+        normalized =
+            static_regex!(r"\$TEST_BUILD_DIR/(?P<filename>[^\.]+).long-type-(?P<hash>\d+).txt")
+                .replace_all(&normalized, |caps: &Captures<'_>| {
+                    format!(
+                        "$TEST_BUILD_DIR/{filename}.long-type-$LONG_TYPE_HASH.txt",
+                        filename = &caps["filename"]
+                    )
+                })
+                .into_owned();
+
         normalized = normalized.replace("\t", "\\t"); // makes tabs visible
 
         // Remove test annotations like `//~ ERROR text` from the output,
diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs
index 9bb3993223e..8900752bd4b 100644
--- a/src/tools/compiletest/src/runtest/run_make.rs
+++ b/src/tools/compiletest/src/runtest/run_make.rs
@@ -9,171 +9,10 @@ use crate::util::{copy_dir_all, dylib_env_var};
 
 impl TestCx<'_> {
     pub(super) fn run_rmake_test(&self) {
-        let test_dir = &self.testpaths.file;
-        if test_dir.join("rmake.rs").exists() {
-            self.run_rmake_v2_test();
-        } else if test_dir.join("Makefile").exists() {
-            self.run_rmake_legacy_test();
-        } else {
-            self.fatal("failed to find either `rmake.rs` or `Makefile`")
-        }
-    }
-
-    fn run_rmake_legacy_test(&self) {
-        let cwd = env::current_dir().unwrap();
-
-        // FIXME(Zalathar): This should probably be `output_base_dir` to avoid
-        // an unnecessary extra subdirectory, but since legacy Makefile tests
-        // are hopefully going away, it seems safer to leave this perilous code
-        // as-is until it can all be deleted.
-        let tmpdir = cwd.join(self.output_base_name());
-        ignore_not_found(|| recursive_remove(&tmpdir)).unwrap();
-
-        fs::create_dir_all(&tmpdir).unwrap();
-
-        let host = &self.config.host;
-        let make = if host.contains("dragonfly")
-            || host.contains("freebsd")
-            || host.contains("netbsd")
-            || host.contains("openbsd")
-            || host.contains("aix")
-        {
-            "gmake"
-        } else {
-            "make"
-        };
-
-        let mut cmd = Command::new(make);
-        cmd.current_dir(&self.testpaths.file)
-            .stdout(Stdio::piped())
-            .stderr(Stdio::piped())
-            .env("TARGET", &self.config.target)
-            .env("PYTHON", &self.config.python)
-            .env("S", &self.config.src_root)
-            .env("RUST_BUILD_STAGE", &self.config.stage_id)
-            .env("RUSTC", cwd.join(&self.config.rustc_path))
-            .env("TMPDIR", &tmpdir)
-            .env("LD_LIB_PATH_ENVVAR", dylib_env_var())
-            .env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path))
-            .env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path))
-            .env("LLVM_COMPONENTS", &self.config.llvm_components)
-            // We for sure don't want these tests to run in parallel, so make
-            // sure they don't have access to these vars if we run via `make`
-            // at the top level
-            .env_remove("MAKEFLAGS")
-            .env_remove("MFLAGS")
-            .env_remove("CARGO_MAKEFLAGS");
-
-        if let Some(ref cargo) = self.config.cargo_path {
-            cmd.env("CARGO", cwd.join(cargo));
-        }
-
-        if let Some(ref rustdoc) = self.config.rustdoc_path {
-            cmd.env("RUSTDOC", cwd.join(rustdoc));
-        }
-
-        if let Some(ref node) = self.config.nodejs {
-            cmd.env("NODE", node);
-        }
-
-        if let Some(ref linker) = self.config.target_linker {
-            cmd.env("RUSTC_LINKER", linker);
-        }
-
-        if let Some(ref clang) = self.config.run_clang_based_tests_with {
-            cmd.env("CLANG", clang);
-        }
-
-        if let Some(ref filecheck) = self.config.llvm_filecheck {
-            cmd.env("LLVM_FILECHECK", filecheck);
-        }
-
-        if let Some(ref llvm_bin_dir) = self.config.llvm_bin_dir {
-            cmd.env("LLVM_BIN_DIR", llvm_bin_dir);
-        }
-
-        if let Some(ref remote_test_client) = self.config.remote_test_client {
-            cmd.env("REMOTE_TEST_CLIENT", remote_test_client);
-        }
-
-        // We don't want RUSTFLAGS set from the outside to interfere with
-        // compiler flags set in the test cases:
-        cmd.env_remove("RUSTFLAGS");
-
-        // Use dynamic musl for tests because static doesn't allow creating dylibs
-        if self.config.host.contains("musl") {
-            cmd.env("RUSTFLAGS", "-Ctarget-feature=-crt-static").env("IS_MUSL_HOST", "1");
-        }
-
-        if self.config.bless {
-            cmd.env("RUSTC_BLESS_TEST", "--bless");
-            // Assume this option is active if the environment variable is "defined", with _any_ value.
-            // As an example, a `Makefile` can use this option by:
-            //
-            //   ifdef RUSTC_BLESS_TEST
-            //       cp "$(TMPDIR)"/actual_something.ext expected_something.ext
-            //   else
-            //       $(DIFF) expected_something.ext "$(TMPDIR)"/actual_something.ext
-            //   endif
-        }
-
-        if self.config.target.contains("msvc") && !self.config.cc.is_empty() {
-            // We need to pass a path to `lib.exe`, so assume that `cc` is `cl.exe`
-            // and that `lib.exe` lives next to it.
-            let lib = Path::new(&self.config.cc).parent().unwrap().join("lib.exe");
-
-            // MSYS doesn't like passing flags of the form `/foo` as it thinks it's
-            // a path and instead passes `C:\msys64\foo`, so convert all
-            // `/`-arguments to MSVC here to `-` arguments.
-            let cflags = self
-                .config
-                .cflags
-                .split(' ')
-                .map(|s| s.replace("/", "-"))
-                .collect::<Vec<_>>()
-                .join(" ");
-            let cxxflags = self
-                .config
-                .cxxflags
-                .split(' ')
-                .map(|s| s.replace("/", "-"))
-                .collect::<Vec<_>>()
-                .join(" ");
-
-            cmd.env("IS_MSVC", "1")
-                .env("IS_WINDOWS", "1")
-                .env("MSVC_LIB", format!("'{}' -nologo", lib.display()))
-                .env("MSVC_LIB_PATH", format!("{}", lib.display()))
-                .env("CC", format!("'{}' {}", self.config.cc, cflags))
-                .env("CXX", format!("'{}' {}", &self.config.cxx, cxxflags));
-        } else {
-            cmd.env("CC", format!("{} {}", self.config.cc, self.config.cflags))
-                .env("CXX", format!("{} {}", self.config.cxx, self.config.cxxflags))
-                .env("AR", &self.config.ar);
-
-            if self.config.target.contains("windows") {
-                cmd.env("IS_WINDOWS", "1");
-            }
-        }
-
-        let (output, truncated) =
-            self.read2_abbreviated(cmd.spawn().expect("failed to spawn `make`"));
-        if !output.status.success() {
-            let res = ProcRes {
-                status: output.status,
-                stdout: String::from_utf8_lossy(&output.stdout).into_owned(),
-                stderr: String::from_utf8_lossy(&output.stderr).into_owned(),
-                truncated,
-                cmdline: format!("{:?}", cmd),
-            };
-            self.fatal_proc_rec("make failed", &res);
-        }
-    }
-
-    fn run_rmake_v2_test(&self) {
         // For `run-make` V2, we need to perform 2 steps to build and run a `run-make` V2 recipe
         // (`rmake.rs`) to run the actual tests. The support library is already built as a tool rust
-        // library and is available under `build/$TARGET/stageN-tools-bin/librun_make_support.rlib`.
+        // library and is available under
+        // `build/$HOST/stage0-bootstrap-tools/$TARGET/release/librun_make_support.rlib`.
         //
         // 1. We need to build the recipe `rmake.rs` as a binary and link in the `run_make_support`
         //    library.
@@ -191,8 +30,6 @@ impl TestCx<'_> {
         // recipes to `remove_dir_all($TMPDIR)` without running into issues related trying to remove
         // a currently running executable because the recipe executable is not under the
         // `rmake_out/` directory.
-        //
-        // This setup intentionally diverges from legacy Makefile run-make tests.
         let base_dir = self.output_base_dir();
         ignore_not_found(|| recursive_remove(&base_dir)).unwrap();
 
@@ -224,25 +61,21 @@ impl TestCx<'_> {
         //
         // ```
         // build/<target_triple>/
-        // ├── stageN-tools-bin/
-        // │   └── librun_make_support.rlib       // <- support rlib itself
-        // ├── stageN-tools/
-        // │   ├── release/deps/                  // <- deps of deps
-        // │   └── <host_triple>/release/deps/    // <- deps
+        // ├── stage0-bootstrap-tools/
+        // │   ├── <host_triple>/release/librun_make_support.rlib   // <- support rlib itself
+        // │   ├── <host_triple>/release/deps/                      // <- deps
+        // │   └── release/deps/                                    // <- deps of deps
         // ```
         //
         // FIXME(jieyouxu): there almost certainly is a better way to do this (specifically how the
-        // support lib and its deps are organized, can't we copy them to the tools-bin dir as
-        // well?), but this seems to work for now.
+        // support lib and its deps are organized), but this seems to work for now.
 
-        let stage_number = self.config.stage;
+        let tools_bin = host_build_root.join("stage0-bootstrap-tools");
+        let support_host_path = tools_bin.join(&self.config.host).join("release");
+        let support_lib_path = support_host_path.join("librun_make_support.rlib");
 
-        let stage_tools_bin = host_build_root.join(format!("stage{stage_number}-tools-bin"));
-        let support_lib_path = stage_tools_bin.join("librun_make_support.rlib");
-
-        let stage_tools = host_build_root.join(format!("stage{stage_number}-tools"));
-        let support_lib_deps = stage_tools.join(&self.config.host).join("release").join("deps");
-        let support_lib_deps_deps = stage_tools.join("release").join("deps");
+        let support_lib_deps = support_host_path.join("deps");
+        let support_lib_deps_deps = tools_bin.join("release").join("deps");
 
         // To compile the recipe with rustc, we need to provide suitable dynamic library search
         // paths to rustc. This includes both:
@@ -253,12 +86,6 @@ impl TestCx<'_> {
         let base_dylib_search_paths =
             Vec::from_iter(env::split_paths(&env::var(dylib_env_var()).unwrap()));
 
-        let host_dylib_search_paths = {
-            let mut paths = vec![self.config.compile_lib_path.clone()];
-            paths.extend(base_dylib_search_paths.iter().cloned());
-            paths
-        };
-
         // Calculate the paths of the recipe binary. As previously discussed, this is placed at
         // `<base_dir>/<bin_name>` with `bin_name` being `rmake` or `rmake.exe` depending on
         // platform.
@@ -268,7 +95,15 @@ impl TestCx<'_> {
             p
         };
 
-        let mut rustc = Command::new(&self.config.rustc_path);
+        // run-make-support and run-make tests are compiled using the stage0 compiler
+        // If the stage is 0, then the compiler that we test (either bootstrap or an explicitly
+        // set compiler) is the one that actually compiled run-make-support.
+        let stage0_rustc = self
+            .config
+            .stage0_rustc_path
+            .as_ref()
+            .expect("stage0 rustc is required to run run-make tests");
+        let mut rustc = Command::new(&stage0_rustc);
         rustc
             .arg("-o")
             .arg(&recipe_bin)
@@ -282,35 +117,12 @@ impl TestCx<'_> {
             .arg(format!("run_make_support={}", &support_lib_path.to_string_lossy()))
             .arg("--edition=2021")
             .arg(&self.testpaths.file.join("rmake.rs"))
-            .arg("-Cprefer-dynamic")
-            // Provide necessary library search paths for rustc.
-            .env(dylib_env_var(), &env::join_paths(host_dylib_search_paths).unwrap());
+            .arg("-Cprefer-dynamic");
 
         // In test code we want to be very pedantic about values being silently discarded that are
         // annotated with `#[must_use]`.
         rustc.arg("-Dunused_must_use");
 
-        // > `cg_clif` uses `COMPILETEST_FORCE_STAGE0=1 ./x.py test --stage 0` for running the rustc
-        // > test suite. With the introduction of rmake.rs this broke. `librun_make_support.rlib` is
-        // > compiled using the bootstrap rustc wrapper which sets `--sysroot
-        // > build/aarch64-unknown-linux-gnu/stage0-sysroot`, but then compiletest will compile
-        // > `rmake.rs` using the sysroot of the bootstrap compiler causing it to not find the
-        // > `libstd.rlib` against which `librun_make_support.rlib` is compiled.
-        //
-        // The gist here is that we have to pass the proper stage0 sysroot if we want
-        //
-        // ```
-        // $ COMPILETEST_FORCE_STAGE0=1 ./x test run-make --stage 0
-        // ```
-        //
-        // to work correctly.
-        //
-        // See <https://github.com/rust-lang/rust/pull/122248> for more background.
-        let stage0_sysroot = host_build_root.join("stage0-sysroot");
-        if std::env::var_os("COMPILETEST_FORCE_STAGE0").is_some() {
-            rustc.arg("--sysroot").arg(&stage0_sysroot);
-        }
-
         // Now run rustc to build the recipe.
         let res = self.run_command_to_procres(&mut rustc);
         if !res.status.success() {
@@ -320,35 +132,24 @@ impl TestCx<'_> {
         // To actually run the recipe, we have to provide the recipe with a bunch of information
         // provided through env vars.
 
-        // Compute stage-specific standard library paths.
-        let stage_std_path = host_build_root.join(format!("stage{stage_number}")).join("lib");
-
         // Compute dynamic library search paths for recipes.
+        // These dylib directories are needed to **execute the recipe**.
         let recipe_dylib_search_paths = {
             let mut paths = base_dylib_search_paths.clone();
-
-            // For stage 0, we need to explicitly include the stage0-sysroot libstd dylib.
-            // See <https://github.com/rust-lang/rust/issues/135373>.
-            if std::env::var_os("COMPILETEST_FORCE_STAGE0").is_some() {
-                paths.push(
-                    stage0_sysroot.join("lib").join("rustlib").join(&self.config.host).join("lib"),
-                );
-            }
-
-            paths.push(support_lib_path.parent().unwrap().to_path_buf());
-            paths.push(stage_std_path.join("rustlib").join(&self.config.host).join("lib"));
-            paths
-        };
-
-        // Compute runtime library search paths for recipes. This is target-specific.
-        let target_runtime_dylib_search_paths = {
-            let mut paths = vec![rmake_out_dir.clone()];
-            paths.extend(base_dylib_search_paths.iter().cloned());
+            paths.push(
+                stage0_rustc
+                    .parent()
+                    .unwrap()
+                    .parent()
+                    .unwrap()
+                    .join("lib")
+                    .join("rustlib")
+                    .join(&self.config.host)
+                    .join("lib"),
+            );
             paths
         };
 
-        // FIXME(jieyouxu): please rename `TARGET_RPATH_ENV`, `HOST_RPATH_DIR` and
-        // `TARGET_RPATH_DIR`, it is **extremely** confusing!
         let mut cmd = Command::new(&recipe_bin);
         cmd.current_dir(&rmake_out_dir)
             .stdout(Stdio::piped())
@@ -357,9 +158,14 @@ impl TestCx<'_> {
             // example, this could be `LD_LIBRARY_PATH` on some linux distros but `PATH` on Windows.
             .env("LD_LIB_PATH_ENVVAR", dylib_env_var())
             // Provide the dylib search paths.
+            // This is required to run the **recipe** itself.
             .env(dylib_env_var(), &env::join_paths(recipe_dylib_search_paths).unwrap())
-            // Provide runtime dylib search paths.
-            .env("TARGET_RPATH_ENV", &env::join_paths(target_runtime_dylib_search_paths).unwrap())
+            // Provide the directory to libraries that are needed to run the *compiler* invoked
+            // by the recipe.
+            .env("HOST_RUSTC_DYLIB_PATH", &self.config.compile_lib_path)
+            // Provide the directory to libraries that might be needed to run binaries created
+            // by a compiler invoked by the recipe.
+            .env("TARGET_EXE_DYLIB_PATH", &self.config.run_lib_path)
             // Provide the target.
             .env("TARGET", &self.config.target)
             // Some tests unfortunately still need Python, so provide path to a Python interpreter.
@@ -370,13 +176,6 @@ impl TestCx<'_> {
             .env("BUILD_ROOT", &host_build_root)
             // Provide path to stage-corresponding rustc.
             .env("RUSTC", &self.config.rustc_path)
-            // Provide the directory to libraries that are needed to run the *compiler*. This is not
-            // to be confused with `TARGET_RPATH_ENV` or `TARGET_RPATH_DIR`. This is needed if the
-            // recipe wants to invoke rustc.
-            .env("HOST_RPATH_DIR", &self.config.compile_lib_path)
-            // Provide the directory to libraries that might be needed to run compiled binaries
-            // (further compiled by the recipe!).
-            .env("TARGET_RPATH_DIR", &self.config.run_lib_path)
             // Provide which LLVM components are available (e.g. which LLVM components are provided
             // through a specific CI runner).
             .env("LLVM_COMPONENTS", &self.config.llvm_components);
diff --git a/src/tools/jsondocck/src/main.rs b/src/tools/jsondocck/src/main.rs
index 7bfa7e3355d..54249fbd9ae 100644
--- a/src/tools/jsondocck/src/main.rs
+++ b/src/tools/jsondocck/src/main.rs
@@ -1,6 +1,6 @@
 use std::borrow::Cow;
 use std::process::ExitCode;
-use std::sync::OnceLock;
+use std::sync::LazyLock;
 use std::{env, fs};
 
 use regex::{Regex, RegexBuilder};
@@ -151,8 +151,7 @@ impl CommandKind {
     }
 }
 
-static LINE_PATTERN: OnceLock<Regex> = OnceLock::new();
-fn line_pattern() -> Regex {
+static LINE_PATTERN: LazyLock<Regex> = LazyLock::new(|| {
     RegexBuilder::new(
         r#"
         //@\s+
@@ -165,7 +164,19 @@ fn line_pattern() -> Regex {
     .unicode(true)
     .build()
     .unwrap()
-}
+});
+
+static DEPRECATED_LINE_PATTERN: LazyLock<Regex> = LazyLock::new(|| {
+    RegexBuilder::new(
+        r#"
+        //\s+@
+    "#,
+    )
+    .ignore_whitespace(true)
+    .unicode(true)
+    .build()
+    .unwrap()
+});
 
 fn print_err(msg: &str, lineno: usize) {
     eprintln!("Invalid command: {} on line {}", msg, lineno)
@@ -184,21 +195,23 @@ fn get_commands(template: &str) -> Result<Vec<Command>, ()> {
     for (lineno, line) in file.split('\n').enumerate() {
         let lineno = lineno + 1;
 
-        let cap = match LINE_PATTERN.get_or_init(line_pattern).captures(line) {
-            Some(c) => c,
-            None => continue,
+        if DEPRECATED_LINE_PATTERN.is_match(line) {
+            print_err("Deprecated command syntax, replace `// @` with `//@ `", lineno);
+            errors = true;
+            continue;
+        }
+
+        let Some(cap) = LINE_PATTERN.captures(line) else {
+            continue;
         };
 
-        let negated = cap.name("negated").unwrap().as_str() == "!";
+        let negated = &cap["negated"] == "!";
 
         let args_str = &cap["args"];
-        let args = match shlex::split(args_str) {
-            Some(args) => args,
-            None => {
-                print_err(&format!("Invalid arguments to shlex::split: `{args_str}`",), lineno);
-                errors = true;
-                continue;
-            }
+        let Some(args) = shlex::split(args_str) else {
+            print_err(&format!("Invalid arguments to shlex::split: `{args_str}`",), lineno);
+            errors = true;
+            continue;
         };
 
         if let Some((kind, path)) = CommandKind::parse(&cap["cmd"], negated, &args) {
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 92f8fa089b0..f6fd106fa52 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-1c3b035542775e9a5decc93167d351b062942d32
+30f168ef811aec63124eac677e14699baa9395bd
diff --git a/src/tools/miri/tests/pass/unsized.rs b/src/tools/miri/tests/pass/unsized.rs
index 5c6929882f6..6ad06354302 100644
--- a/src/tools/miri/tests/pass/unsized.rs
+++ b/src/tools/miri/tests/pass/unsized.rs
@@ -1,22 +1,8 @@
 //@revisions: stack tree
 //@[tree]compile-flags: -Zmiri-tree-borrows
-#![feature(unsized_tuple_coercion)]
 #![feature(unsized_fn_params)]
 #![feature(custom_mir, core_intrinsics)]
 
-use std::mem;
-
-fn unsized_tuple() {
-    let x: &(i32, i32, [i32]) = &(0, 1, [2, 3]);
-    let y: &(i32, i32, [i32]) = &(0, 1, [2, 3, 4]);
-    let mut a = [y, x];
-    a.sort();
-    assert_eq!(a, [x, y]);
-
-    assert_eq!(&format!("{:?}", a), "[(0, 1, [2, 3]), (0, 1, [2, 3, 4])]");
-    assert_eq!(mem::size_of_val(x), 16);
-}
-
 fn unsized_params() {
     pub fn f0(_f: dyn FnOnce()) {}
     pub fn f1(_s: str) {}
@@ -56,7 +42,6 @@ fn unsized_field_projection() {
 }
 
 fn main() {
-    unsized_tuple();
     unsized_params();
     unsized_field_projection();
 }
diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs
index 565721a9093..3111149f2ae 100644
--- a/src/tools/opt-dist/src/main.rs
+++ b/src/tools/opt-dist/src/main.rs
@@ -389,6 +389,7 @@ fn main() -> anyhow::Result<()> {
             "clippy",
             "miri",
             "rustfmt",
+            "gcc",
         ] {
             build_args.extend(["--skip".to_string(), target.to_string()]);
         }
diff --git a/src/tools/opt-dist/src/metrics.rs b/src/tools/opt-dist/src/metrics.rs
index 89c4cb12d4c..0a745566eb5 100644
--- a/src/tools/opt-dist/src/metrics.rs
+++ b/src/tools/opt-dist/src/metrics.rs
@@ -1,33 +1,10 @@
 use std::time::Duration;
 
-use build_helper::metrics::{JsonNode, JsonRoot};
+use build_helper::metrics::{BuildStep, JsonRoot, format_build_steps};
 use camino::Utf8Path;
 
 use crate::timer::TimerSection;
 
-#[derive(Clone, Debug)]
-pub struct BuildStep {
-    r#type: String,
-    children: Vec<BuildStep>,
-    duration: Duration,
-}
-
-impl BuildStep {
-    pub fn find_all_by_type(&self, r#type: &str) -> Vec<&BuildStep> {
-        let mut result = Vec::new();
-        self.find_by_type(r#type, &mut result);
-        result
-    }
-    fn find_by_type<'a>(&'a self, r#type: &str, result: &mut Vec<&'a BuildStep>) {
-        if self.r#type == r#type {
-            result.push(self);
-        }
-        for child in &self.children {
-            child.find_by_type(r#type, result);
-        }
-    }
-}
-
 /// Loads the metrics of the most recent bootstrap execution from a metrics.json file.
 pub fn load_metrics(path: &Utf8Path) -> anyhow::Result<BuildStep> {
     let content = std::fs::read(path.as_std_path())?;
@@ -37,30 +14,7 @@ pub fn load_metrics(path: &Utf8Path) -> anyhow::Result<BuildStep> {
         .pop()
         .ok_or_else(|| anyhow::anyhow!("No bootstrap invocation found in metrics file"))?;
 
-    fn parse(node: JsonNode) -> Option<BuildStep> {
-        match node {
-            JsonNode::RustbuildStep {
-                type_: kind,
-                children,
-                duration_excluding_children_sec,
-                ..
-            } => {
-                let children: Vec<_> = children.into_iter().filter_map(parse).collect();
-                let children_duration = children.iter().map(|c| c.duration).sum::<Duration>();
-                Some(BuildStep {
-                    r#type: kind.to_string(),
-                    children,
-                    duration: children_duration
-                        + Duration::from_secs_f64(duration_excluding_children_sec),
-                })
-            }
-            JsonNode::TestSuite(_) => None,
-        }
-    }
-
-    let duration = Duration::from_secs_f64(invocation.duration_including_children_sec);
-    let children: Vec<_> = invocation.children.into_iter().filter_map(parse).collect();
-    Ok(BuildStep { r#type: "root".to_string(), children, duration })
+    Ok(BuildStep::from_invocation(&invocation))
 }
 
 /// Logs the individual metrics in a table and add Rustc and LLVM durations to the passed
@@ -82,27 +36,6 @@ pub fn record_metrics(metrics: &BuildStep, timer: &mut TimerSection) {
         timer.add_duration("Rustc", rustc_duration);
     }
 
-    log_metrics(metrics);
-}
-
-fn log_metrics(metrics: &BuildStep) {
-    use std::fmt::Write;
-
-    let mut substeps: Vec<(u32, &BuildStep)> = Vec::new();
-
-    fn visit<'a>(step: &'a BuildStep, level: u32, substeps: &mut Vec<(u32, &'a BuildStep)>) {
-        substeps.push((level, step));
-        for child in &step.children {
-            visit(child, level + 1, substeps);
-        }
-    }
-
-    visit(metrics, 0, &mut substeps);
-
-    let mut output = String::new();
-    for (level, step) in substeps {
-        let label = format!("{}{}", ".".repeat(level as usize), step.r#type);
-        writeln!(output, "{label:<65}{:>8.2}s", step.duration.as_secs_f64()).unwrap();
-    }
+    let output = format_build_steps(metrics);
     log::info!("Build step durations\n{output}");
 }
diff --git a/src/tools/run-make-support/src/artifact_names.rs b/src/tools/run-make-support/src/artifact_names.rs
index 0d7b5cb9838..8968f831542 100644
--- a/src/tools/run-make-support/src/artifact_names.rs
+++ b/src/tools/run-make-support/src/artifact_names.rs
@@ -8,23 +8,6 @@ use crate::targets::is_msvc;
 /// Construct the static library name based on the target.
 #[must_use]
 pub fn static_lib_name(name: &str) -> String {
-    // See tools.mk (irrelevant lines omitted):
-    //
-    // ```makefile
-    // ifeq ($(UNAME),Darwin)
-    //     STATICLIB = $(TMPDIR)/lib$(1).a
-    // else
-    //     ifdef IS_WINDOWS
-    //         ifdef IS_MSVC
-    //             STATICLIB = $(TMPDIR)/$(1).lib
-    //         else
-    //             STATICLIB = $(TMPDIR)/lib$(1).a
-    //         endif
-    //     else
-    //         STATICLIB = $(TMPDIR)/lib$(1).a
-    //     endif
-    // endif
-    // ```
     assert!(!name.contains(char::is_whitespace), "static library name cannot contain whitespace");
 
     if is_msvc() { format!("{name}.lib") } else { format!("lib{name}.a") }
diff --git a/src/tools/run-make-support/src/external_deps/c_cxx_compiler/cc.rs b/src/tools/run-make-support/src/external_deps/c_cxx_compiler/cc.rs
index becb91ae989..0e6d6ea6075 100644
--- a/src/tools/run-make-support/src/external_deps/c_cxx_compiler/cc.rs
+++ b/src/tools/run-make-support/src/external_deps/c_cxx_compiler/cc.rs
@@ -80,17 +80,6 @@ impl Cc {
 
     /// Specify `-o` or `-Fe`/`-Fo` depending on platform/compiler.
     pub fn out_exe(&mut self, name: &str) -> &mut Self {
-        // Ref: tools.mk (irrelevant lines omitted):
-        //
-        // ```makefile
-        // ifdef IS_MSVC
-        //     OUT_EXE=-Fe:`cygpath -w $(TMPDIR)/$(call BIN,$(1))` \
-        //         -Fo:`cygpath -w $(TMPDIR)/$(1).obj`
-        // else
-        //     OUT_EXE=-o $(TMPDIR)/$(1)
-        // endif
-        // ```
-
         let mut path = std::path::PathBuf::from(name);
 
         if is_msvc() {
diff --git a/src/tools/run-make-support/src/external_deps/c_cxx_compiler/extras.rs b/src/tools/run-make-support/src/external_deps/c_cxx_compiler/extras.rs
index 49210d75e06..ca6ab3275c4 100644
--- a/src/tools/run-make-support/src/external_deps/c_cxx_compiler/extras.rs
+++ b/src/tools/run-make-support/src/external_deps/c_cxx_compiler/extras.rs
@@ -2,36 +2,6 @@ use crate::{is_msvc, is_windows, uname};
 
 /// `EXTRACFLAGS`
 pub fn extra_c_flags() -> Vec<&'static str> {
-    // Adapted from tools.mk (trimmed):
-    //
-    // ```makefile
-    // ifdef IS_WINDOWS
-    //     ifdef IS_MSVC
-    //         EXTRACFLAGS := ws2_32.lib userenv.lib advapi32.lib bcrypt.lib ntdll.lib synchronization.lib
-    //     else
-    //         EXTRACFLAGS := -lws2_32 -luserenv -lbcrypt -lntdll -lsynchronization
-    //     endif
-    // else
-    //     ifeq ($(UNAME),Darwin)
-    //         EXTRACFLAGS := -lresolv
-    //     else
-    //         ifeq ($(UNAME),FreeBSD)
-    //             EXTRACFLAGS := -lm -lpthread -lgcc_s
-    //         else
-    //             ifeq ($(UNAME),SunOS)
-    //                 EXTRACFLAGS := -lm -lpthread -lposix4 -lsocket -lresolv
-    //             else
-    //                 ifeq ($(UNAME),OpenBSD)
-    //                     EXTRACFLAGS := -lm -lpthread -lc++abi
-    //                 else
-    //                     EXTRACFLAGS := -lm -lrt -ldl -lpthread
-    //                 endif
-    //             endif
-    //         endif
-    //     endif
-    // endif
-    // ```
-
     if is_windows() {
         if is_msvc() {
             vec![
@@ -60,31 +30,6 @@ pub fn extra_c_flags() -> Vec<&'static str> {
 
 /// `EXTRACXXFLAGS`
 pub fn extra_cxx_flags() -> Vec<&'static str> {
-    // Adapted from tools.mk (trimmed):
-    //
-    // ```makefile
-    // ifdef IS_WINDOWS
-    //     ifdef IS_MSVC
-    //     else
-    //         EXTRACXXFLAGS := -lstdc++
-    //     endif
-    // else
-    //     ifeq ($(UNAME),Darwin)
-    //         EXTRACXXFLAGS := -lc++
-    //     else
-    //         ifeq ($(UNAME),FreeBSD)
-    //         else
-    //             ifeq ($(UNAME),SunOS)
-    //             else
-    //                 ifeq ($(UNAME),OpenBSD)
-    //                 else
-    //                     EXTRACXXFLAGS := -lstdc++
-    //                 endif
-    //             endif
-    //         endif
-    //     endif
-    // endif
-    // ```
     if is_windows() {
         if is_msvc() { vec![] } else { vec!["-lstdc++"] }
     } else {
diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs
index 710ba025830..0e2239147f1 100644
--- a/src/tools/run-make-support/src/external_deps/rustc.rs
+++ b/src/tools/run-make-support/src/external_deps/rustc.rs
@@ -5,7 +5,7 @@ use std::str::FromStr as _;
 use crate::command::Command;
 use crate::env::env_var;
 use crate::path_helpers::cwd;
-use crate::util::set_host_rpath;
+use crate::util::set_host_compiler_dylib_path;
 use crate::{is_aix, is_darwin, is_msvc, is_windows, uname};
 
 /// Construct a new `rustc` invocation. This will automatically set the library
@@ -15,8 +15,8 @@ pub fn rustc() -> Rustc {
     Rustc::new()
 }
 
-/// Construct a plain `rustc` invocation with no flags set. Note that [`set_host_rpath`]
-/// still presets the environment variable `HOST_RPATH_DIR` by default.
+/// Construct a plain `rustc` invocation with no flags set. Note that [`set_host_compiler_dylib_path`]
+/// still presets the environment variable `HOST_RUSTC_DYLIB_PATH` by default.
 #[track_caller]
 pub fn bare_rustc() -> Rustc {
     Rustc::bare()
@@ -44,7 +44,7 @@ pub fn rustc_path() -> String {
 #[track_caller]
 fn setup_common() -> Command {
     let mut cmd = Command::new(rustc_path());
-    set_host_rpath(&mut cmd);
+    set_host_compiler_dylib_path(&mut cmd);
     cmd
 }
 
@@ -365,31 +365,6 @@ impl Rustc {
 
     /// `EXTRARSCXXFLAGS`
     pub fn extra_rs_cxx_flags(&mut self) -> &mut Self {
-        // Adapted from tools.mk (trimmed):
-        //
-        // ```makefile
-        // ifdef IS_WINDOWS
-        //     ifdef IS_MSVC
-        //     else
-        //         EXTRARSCXXFLAGS := -lstatic:-bundle=stdc++
-        //     endif
-        // else
-        //     ifeq ($(UNAME),Darwin)
-        //         EXTRARSCXXFLAGS := -lc++
-        //     else
-        //         ifeq ($(UNAME),FreeBSD)
-        //         else
-        //             ifeq ($(UNAME),SunOS)
-        //             else
-        //                 ifeq ($(UNAME),OpenBSD)
-        //                 else
-        //                     EXTRARSCXXFLAGS := -lstdc++
-        //                 endif
-        //             endif
-        //         endif
-        //     endif
-        // endif
-        // ```
         if is_windows() {
             // So this is a bit hacky: we can't use the DLL version of libstdc++ because
             // it pulls in the DLL version of libgcc, which means that we end up with 2
diff --git a/src/tools/run-make-support/src/external_deps/rustdoc.rs b/src/tools/run-make-support/src/external_deps/rustdoc.rs
index 3c0e9c82f0b..433a57cd9fa 100644
--- a/src/tools/run-make-support/src/external_deps/rustdoc.rs
+++ b/src/tools/run-make-support/src/external_deps/rustdoc.rs
@@ -2,16 +2,10 @@ use std::ffi::OsStr;
 use std::path::Path;
 
 use crate::command::Command;
-use crate::env::{env_var, env_var_os};
-use crate::util::set_host_rpath;
+use crate::env::env_var;
+use crate::util::set_host_compiler_dylib_path;
 
-/// Construct a plain `rustdoc` invocation with no flags set.
-#[track_caller]
-pub fn bare_rustdoc() -> Rustdoc {
-    Rustdoc::bare()
-}
-
-/// Construct a new `rustdoc` invocation with `-L $(TARGET_RPATH_DIR)` set.
+/// Construct a new `rustdoc` invocation.
 #[track_caller]
 pub fn rustdoc() -> Rustdoc {
     Rustdoc::new()
@@ -29,23 +23,15 @@ crate::macros::impl_common_helpers!(Rustdoc);
 fn setup_common() -> Command {
     let rustdoc = env_var("RUSTDOC");
     let mut cmd = Command::new(rustdoc);
-    set_host_rpath(&mut cmd);
+    set_host_compiler_dylib_path(&mut cmd);
     cmd
 }
 
 impl Rustdoc {
     /// Construct a bare `rustdoc` invocation.
     #[track_caller]
-    pub fn bare() -> Self {
-        let cmd = setup_common();
-        Self { cmd }
-    }
-
-    /// Construct a `rustdoc` invocation with `-L $(TARGET_RPATH_DIR)` set.
-    #[track_caller]
     pub fn new() -> Self {
-        let mut cmd = setup_common();
-        cmd.arg("-L").arg(env_var_os("TARGET_RPATH_DIR"));
+        let cmd = setup_common();
         Self { cmd }
     }
 
@@ -132,4 +118,11 @@ impl Rustdoc {
         self.cmd.arg(format);
         self
     }
+
+    /// Specify type(s) of output files to generate.
+    pub fn emit<S: AsRef<str>>(&mut self, kinds: S) -> &mut Self {
+        let kinds = kinds.as_ref();
+        self.cmd.arg(format!("--emit={kinds}"));
+        self
+    }
 }
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index 7e63ab3159a..d40ec9c4116 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -67,7 +67,7 @@ pub use llvm::{
 };
 pub use python::python_command;
 pub use rustc::{aux_build, bare_rustc, rustc, rustc_path, Rustc};
-pub use rustdoc::{bare_rustdoc, rustdoc, Rustdoc};
+pub use rustdoc::{rustdoc, Rustdoc};
 
 /// [`diff`][mod@diff] is implemented in terms of the [similar] library.
 ///
diff --git a/src/tools/run-make-support/src/run.rs b/src/tools/run-make-support/src/run.rs
index 3eeba6fd526..7812863ccc2 100644
--- a/src/tools/run-make-support/src/run.rs
+++ b/src/tools/run-make-support/src/run.rs
@@ -1,10 +1,10 @@
 use std::ffi::OsStr;
-use std::path::{Path, PathBuf};
+use std::path::PathBuf;
 use std::{env, panic};
 
 use crate::command::{Command, CompletedProcess};
-use crate::util::{handle_failed_output, set_host_rpath};
-use crate::{cwd, env_var, is_windows};
+use crate::util::handle_failed_output;
+use crate::{cwd, env_var};
 
 #[track_caller]
 fn run_common(name: &str, args: Option<&[&str]>) -> Command {
@@ -18,10 +18,11 @@ fn run_common(name: &str, args: Option<&[&str]>) -> Command {
             cmd.arg(arg);
         }
     }
+
     cmd.env(&ld_lib_path_envvar, {
         let mut paths = vec![];
         paths.push(cwd());
-        for p in env::split_paths(&env_var("TARGET_RPATH_ENV")) {
+        for p in env::split_paths(&env_var("TARGET_EXE_DYLIB_PATH")) {
             paths.push(p.to_path_buf());
         }
         for p in env::split_paths(&env_var(&ld_lib_path_envvar)) {
@@ -31,15 +32,6 @@ fn run_common(name: &str, args: Option<&[&str]>) -> Command {
     });
     cmd.env("LC_ALL", "C"); // force english locale
 
-    if is_windows() {
-        let mut paths = vec![];
-        for p in env::split_paths(&std::env::var("PATH").unwrap_or(String::new())) {
-            paths.push(p.to_path_buf());
-        }
-        paths.push(Path::new(&env_var("TARGET_RPATH_DIR")).to_path_buf());
-        cmd.env("PATH", env::join_paths(paths.iter()).unwrap());
-    }
-
     cmd
 }
 
@@ -84,7 +76,6 @@ pub fn run_fail(name: &str) -> CompletedProcess {
 #[track_caller]
 pub fn cmd<S: AsRef<OsStr>>(program: S) -> Command {
     let mut command = Command::new(program);
-    set_host_rpath(&mut command);
     command.env("LC_ALL", "C"); // force english locale
     command
 }
diff --git a/src/tools/run-make-support/src/util.rs b/src/tools/run-make-support/src/util.rs
index 703e3ad1c6c..af01758447b 100644
--- a/src/tools/run-make-support/src/util.rs
+++ b/src/tools/run-make-support/src/util.rs
@@ -24,13 +24,13 @@ pub(crate) fn handle_failed_output(
     std::process::exit(1)
 }
 
-/// Set the runtime library path as needed for running the host rustc/rustdoc/etc.
-pub(crate) fn set_host_rpath(cmd: &mut Command) {
+/// Set the runtime library paths as needed for running the host compilers (rustc/rustdoc/etc).
+pub(crate) fn set_host_compiler_dylib_path(cmd: &mut Command) {
     let ld_lib_path_envvar = env_var("LD_LIB_PATH_ENVVAR");
     cmd.env(&ld_lib_path_envvar, {
         let mut paths = vec![];
         paths.push(cwd());
-        paths.push(PathBuf::from(env_var("HOST_RPATH_DIR")));
+        paths.push(PathBuf::from(env_var("HOST_RUSTC_DYLIB_PATH")));
         for p in std::env::split_paths(&env_var(&ld_lib_path_envvar)) {
             paths.push(p.to_path_buf());
         }
diff --git a/src/tools/rust-analyzer/.github/workflows/autopublish.yaml b/src/tools/rust-analyzer/.github/workflows/autopublish.yaml
index e4fa94643ba..d3f0499e434 100644
--- a/src/tools/rust-analyzer/.github/workflows/autopublish.yaml
+++ b/src/tools/rust-analyzer/.github/workflows/autopublish.yaml
@@ -11,7 +11,7 @@ on:
 
 jobs:
   publish:
-    if: ${{ github.repository == 'rust-lang/rust-analyzer' || github.event.action == 'workflow_dispatch' }}
+    if: ${{ github.repository == 'rust-lang/rust-analyzer' || github.event_name == 'workflow_dispatch' }}
     name: publish
     runs-on: ubuntu-latest
     steps:
diff --git a/src/tools/rust-analyzer/.github/workflows/ci.yaml b/src/tools/rust-analyzer/.github/workflows/ci.yaml
index 81b55712d7f..bc770dbe71e 100644
--- a/src/tools/rust-analyzer/.github/workflows/ci.yaml
+++ b/src/tools/rust-analyzer/.github/workflows/ci.yaml
@@ -174,7 +174,7 @@ jobs:
       - name: Install Nodejs
         uses: actions/setup-node@v4
         with:
-          node-version: 18
+          node-version: 22
         if: needs.changes.outputs.typescript == 'true'
 
       - name: Install xvfb
diff --git a/src/tools/rust-analyzer/.github/workflows/fuzz.yml b/src/tools/rust-analyzer/.github/workflows/fuzz.yml
index f88c7f95d5c..7acfcbe351f 100644
--- a/src/tools/rust-analyzer/.github/workflows/fuzz.yml
+++ b/src/tools/rust-analyzer/.github/workflows/fuzz.yml
@@ -19,7 +19,7 @@ env:
 
 jobs:
   rust:
-    if: ${{ github.repository == 'rust-lang/rust-analyzer' || github.event.action == 'workflow_dispatch' }}
+    if: ${{ github.repository == 'rust-lang/rust-analyzer' || github.event_name == 'workflow_dispatch' }}
     name: Rust
     runs-on: ubuntu-latest
     env:
diff --git a/src/tools/rust-analyzer/.github/workflows/publish-libs.yaml b/src/tools/rust-analyzer/.github/workflows/publish-libs.yaml
index 5023a634fde..93ae5675a71 100644
--- a/src/tools/rust-analyzer/.github/workflows/publish-libs.yaml
+++ b/src/tools/rust-analyzer/.github/workflows/publish-libs.yaml
@@ -9,7 +9,7 @@ on:
 
 jobs:
   publish-libs:
-    if: ${{ github.repository == 'rust-lang/rust-analyzer' || github.event.action == 'workflow_dispatch' }}
+    if: ${{ github.repository == 'rust-lang/rust-analyzer' || github.event_name == 'workflow_dispatch' }}
     name: publish
     runs-on: ubuntu-latest
     steps:
diff --git a/src/tools/rust-analyzer/.github/workflows/release.yaml b/src/tools/rust-analyzer/.github/workflows/release.yaml
index fe090267dc9..c8e6de72ce9 100644
--- a/src/tools/rust-analyzer/.github/workflows/release.yaml
+++ b/src/tools/rust-analyzer/.github/workflows/release.yaml
@@ -17,12 +17,12 @@ env:
   RUSTUP_MAX_RETRIES: 10
   FETCH_DEPTH: 0 # pull in the tags for the version string
   MACOSX_DEPLOYMENT_TARGET: 13.0
-  CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER: aarch64-linux-gnu-gcc
-  CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER: arm-linux-gnueabihf-gcc
+  ZIG_VERSION: 0.13.0
+  ZIGBUILD_VERSION: 0.19.8
 
 jobs:
   dist:
-    if: ${{ github.repository == 'rust-lang/rust-analyzer' || github.event.action == 'workflow_dispatch' }}
+    if: ${{ github.repository == 'rust-lang/rust-analyzer' || github.event_name == 'workflow_dispatch' }}
     strategy:
       matrix:
         include:
@@ -36,13 +36,15 @@ jobs:
             code-target: win32-arm64
           - os: ubuntu-latest
             target: x86_64-unknown-linux-gnu
+            zig_target: x86_64-unknown-linux-gnu.2.28
             code-target: linux-x64
-            container: rockylinux:8
           - os: ubuntu-latest
             target: aarch64-unknown-linux-gnu
+            zig_target: aarch64-unknown-linux-gnu.2.28
             code-target: linux-arm64
           - os: ubuntu-latest
             target: arm-unknown-linux-gnueabihf
+            zig_target: arm-unknown-linux-gnueabihf.2.28
             code-target: linux-armhf
           - os: macos-13
             target: x86_64-apple-darwin
@@ -64,40 +66,33 @@ jobs:
         with:
           fetch-depth: ${{ env.FETCH_DEPTH }}
 
-      - name: Install toolchain dependencies
-        if: matrix.container == 'rockylinux:8'
-        shell: bash
-        run: |
-          dnf install -y gcc
-          curl --proto '=https' --tlsv1.2 --retry 10 --retry-connrefused -fsSL "https://sh.rustup.rs" | sh -s -- --profile minimal --default-toolchain none -y
-          echo "${CARGO_HOME:-$HOME/.cargo}/bin" >> $GITHUB_PATH
+      - name: Install Node.js toolchain
+        uses: actions/setup-node@v4
+        with:
+          node-version: 22
 
       - name: Install Rust toolchain
         run: |
           rustup update --no-self-update stable
-          rustup target add ${{ matrix.target }}
           rustup component add rust-src
+          rustup target add ${{ matrix.target }}
 
-      - name: Install Node.js
-        uses: actions/setup-node@v4
-        with:
-          node-version: 18
-
-      - name: Update apt repositories
-        if: matrix.target == 'aarch64-unknown-linux-gnu' || matrix.target == 'arm-unknown-linux-gnueabihf'
-        run: sudo apt-get update
-
-      - name: Install AArch64 target toolchain
-        if: matrix.target == 'aarch64-unknown-linux-gnu'
-        run: sudo apt-get install gcc-aarch64-linux-gnu
-
-      - name: Install ARM target toolchain
-        if: matrix.target == 'arm-unknown-linux-gnueabihf'
-        run: sudo apt-get install gcc-arm-linux-gnueabihf
+      - name: Install Zig toolchain
+        if: ${{ matrix.zig_target }}
+        run: |
+          which cargo
+          curl -L "https://ziglang.org/download/${ZIG_VERSION}/zig-linux-$(uname -m)-${ZIG_VERSION}.tar.xz" | sudo tar JxC /usr/local
+          sudo ln -s "/usr/local/zig-linux-$(uname -m)-${ZIG_VERSION}/zig" /usr/local/bin/zig
+          curl -L "https://github.com/rust-cross/cargo-zigbuild/releases/download/v${ZIGBUILD_VERSION}/cargo-zigbuild-v${ZIGBUILD_VERSION}.x86_64-unknown-linux-musl.tar.gz" | tar zxC ~/.cargo/bin
 
-      - name: Dist
+      - name: Dist (plain)
+        if: ${{ !matrix.zig_target }}
         run: cargo xtask dist --client-patch-version ${{ github.run_number }}
 
+      - name: Dist (using zigbuild)
+        if: ${{ matrix.zig_target }}
+        run: RA_TARGET=${{ matrix.zig_target}} cargo xtask dist --client-patch-version ${{ github.run_number }} --zig
+
       - run: npm ci
         working-directory: editors/code
 
@@ -139,7 +134,7 @@ jobs:
           path: ./dist
 
   dist-x86_64-unknown-linux-musl:
-    if: ${{ github.repository == 'rust-lang/rust-analyzer' || github.event.action == 'workflow_dispatch' }}
+    if: ${{ github.repository == 'rust-lang/rust-analyzer' || github.event_name == 'workflow_dispatch' }}
     name: dist (x86_64-unknown-linux-musl)
     runs-on: ubuntu-latest
     env:
@@ -185,7 +180,7 @@ jobs:
           path: ./dist
 
   publish:
-    if: ${{ github.repository == 'rust-lang/rust-analyzer' || github.event.action == 'workflow_dispatch' }}
+    if: ${{ github.repository == 'rust-lang/rust-analyzer' || github.event_name == 'workflow_dispatch' }}
     name: publish
     runs-on: ubuntu-latest
     needs: ["dist", "dist-x86_64-unknown-linux-musl"]
@@ -193,7 +188,7 @@ jobs:
       - name: Install Nodejs
         uses: actions/setup-node@v4
         with:
-          node-version: 20
+          node-version: 22
 
       - run: echo "TAG=$(date --iso -u)" >> $GITHUB_ENV
         if: github.ref == 'refs/heads/release'
diff --git a/src/tools/rust-analyzer/.typos.toml b/src/tools/rust-analyzer/.typos.toml
index 0f2f9b1b275..e938bddd4b1 100644
--- a/src/tools/rust-analyzer/.typos.toml
+++ b/src/tools/rust-analyzer/.typos.toml
@@ -18,6 +18,8 @@ extend-ignore-re = [
     "INOUT",
     "optin",
     "=Pn",
+    # ignore `// spellchecker:off` until `// spellchecker:on`
+    "(?s)(#|//)\\s*spellchecker:off.*?\\n\\s*(#|//)\\s*spellchecker:on",
 ]
 
 [default.extend-words]
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index 01e6a39f7c9..c57953ba654 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -22,9 +22,6 @@ name = "always-assert"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a1078fa1ce1e34b1872d8611ad921196d76bdd7027e949fbe31231abde201892"
-dependencies = [
- "tracing",
-]
 
 [[package]]
 name = "anyhow"
@@ -1507,9 +1504,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_abi"
-version = "0.97.0"
+version = "0.98.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3829c3355d1681ffeaf1450ec71edcdace6820fe2e86469d8fc1ad45e2c96460"
+checksum = "4b42cccfff8091a4c3397736518774dbad619e82f8def6f70d8e46dbbe396007"
 dependencies = [
  "bitflags 2.7.0",
  "ra-ap-rustc_hashes",
@@ -1519,18 +1516,18 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_hashes"
-version = "0.97.0"
+version = "0.98.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1bd4d6d4c434bec08e02370a4f64a4985312097215a62e82d0f757f3a98e502e"
+checksum = "46d8bd34ed6552c8cac1764106ef5adbeef3e5c7700e0ceb4c83a47a631894fe"
 dependencies = [
  "rustc-stable-hash",
 ]
 
 [[package]]
 name = "ra-ap-rustc_index"
-version = "0.97.0"
+version = "0.98.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bad6fc4bd7522e31096e2de5b0351144fe0684b608791ee26c842bf2da1b19ae"
+checksum = "93799e4dccbbd47f8b66bc0aa42effc1b7077aaee09d8a40b86b8d659b80c7b7"
 dependencies = [
  "ra-ap-rustc_index_macros",
  "smallvec",
@@ -1538,9 +1535,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_index_macros"
-version = "0.97.0"
+version = "0.98.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cfb234e1f84b92be45276c3025bee18789e9bc95bec8789bec961e78edb01c52"
+checksum = "30baa5d00f94ba437a9dcaf7ae074ebe4f367bb05a4c2835e0aa2e7af3463aac"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1549,9 +1546,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_lexer"
-version = "0.97.0"
+version = "0.98.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a3a40bd11dc43d1cb110e730b80620cf8102f4cca8920a02b65954da0ed931f"
+checksum = "3004d1d1b50afe3e1f9cdd428a282da7ffbf5f26dd8bf04af0d651d44e4873d8"
 dependencies = [
  "memchr",
  "unicode-properties",
@@ -1560,9 +1557,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_parse_format"
-version = "0.97.0"
+version = "0.98.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5feb877478994cb4c0c0c7a5116a352eefc0634aefc8636feb00a893fa5b7135"
+checksum = "cb57e5124a64aaaf92c06130fbc1b8e1d547b5a2a96081f1f848e31c211df5d2"
 dependencies = [
  "ra-ap-rustc_index",
  "ra-ap-rustc_lexer",
@@ -1570,9 +1567,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_pattern_analysis"
-version = "0.97.0"
+version = "0.98.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a76774d35934d464c4115908cde16f76a4f7e540fe1eea6b79336c556e37bdd3"
+checksum = "e427c3d30e4bdff28abd6b0ef3e6f4dfab44acd9468a4954eeff8717d8df8819"
 dependencies = [
  "ra-ap-rustc_index",
  "rustc-hash 2.0.0",
@@ -1940,13 +1937,13 @@ dependencies = [
 name = "stdx"
 version = "0.0.0"
 dependencies = [
- "always-assert",
  "backtrace",
  "crossbeam-channel",
  "itertools",
  "jod-thread",
  "libc",
  "miow",
+ "tracing",
  "windows-sys 0.59.0",
 ]
 
diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml
index 1ff36a68e8f..1132acb6474 100644
--- a/src/tools/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/Cargo.toml
@@ -25,7 +25,6 @@ salsa.opt-level = 3
 miniz_oxide.opt-level = 3
 
 [profile.release]
-incremental = true
 # Set this to 1 or 2 to get more useful backtraces in debugger.
 debug = 0
 
@@ -86,12 +85,12 @@ vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" }
 vfs = { path = "./crates/vfs", version = "0.0.0" }
 edition = { path = "./crates/edition", version = "0.0.0" }
 
-ra-ap-rustc_hashes = { version = "0.97", default-features = false }
-ra-ap-rustc_lexer = { version = "0.97", default-features = false }
-ra-ap-rustc_parse_format = { version = "0.97", default-features = false }
-ra-ap-rustc_index = { version = "0.97", default-features = false }
-ra-ap-rustc_abi = { version = "0.97", default-features = false }
-ra-ap-rustc_pattern_analysis = { version = "0.97", default-features = false }
+ra-ap-rustc_hashes = { version = "0.98", default-features = false }
+ra-ap-rustc_lexer = { version = "0.98", default-features = false }
+ra-ap-rustc_parse_format = { version = "0.98", default-features = false }
+ra-ap-rustc_index = { version = "0.98", default-features = false }
+ra-ap-rustc_abi = { version = "0.98", default-features = false }
+ra-ap-rustc_pattern_analysis = { version = "0.98", default-features = false }
 
 # local crates that aren't published to crates.io. These should not have versions.
 
diff --git a/src/tools/rust-analyzer/crates/base-db/Cargo.toml b/src/tools/rust-analyzer/crates/base-db/Cargo.toml
index 788ceb8857e..042dd36488a 100644
--- a/src/tools/rust-analyzer/crates/base-db/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/base-db/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 lz4_flex = { version = "0.11", default-features = false }
diff --git a/src/tools/rust-analyzer/crates/cfg/Cargo.toml b/src/tools/rust-analyzer/crates/cfg/Cargo.toml
index 040bddbd7fd..e887368ef28 100644
--- a/src/tools/rust-analyzer/crates/cfg/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/cfg/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 rustc-hash.workspace = true
diff --git a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml
index 9a448ec14ea..a22961c26c8 100644
--- a/src/tools/rust-analyzer/crates/hir-def/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-def/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 arrayvec.workspace = 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 e9318d146dd..8868bc0cd95 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
@@ -5,7 +5,9 @@
 //!
 //! It is used like this:
 //!
-//! ```
+//! ```ignore
+//! # use hir_def::dyn_map::DynMap;
+//! # use hir_def::dyn_map::Key;
 //! // keys define submaps of a `DynMap`
 //! const STRING_TO_U32: Key<String, u32> = Key::new();
 //! const U32_TO_VEC: Key<u32, Vec<bool>> = Key::new();
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
index 8d5b3eeb28e..382afbcb1dd 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
@@ -883,20 +883,20 @@ pub struct UseTree {
 
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub enum UseTreeKind {
-    /// ```
+    /// ```ignore
     /// use path::to::Item;
     /// use path::to::Item as Renamed;
     /// use path::to::Trait as _;
     /// ```
     Single { path: Interned<ModPath>, alias: Option<ImportAlias> },
 
-    /// ```
+    /// ```ignore
     /// use *;  // (invalid, but can occur in nested tree)
     /// use path::*;
     /// ```
     Glob { path: Option<Interned<ModPath>> },
 
-    /// ```
+    /// ```ignore
     /// use prefix::{self, Item, ...};
     /// ```
     Prefixed { prefix: Option<Interned<ModPath>>, list: Box<[UseTree]> },
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 408d03ff718..a2d0ba3deb8 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
@@ -22,7 +22,7 @@ use hir_expand::{
     db::ExpandDatabase,
     proc_macro::{ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroKind},
     span_map::SpanMapRef,
-    InFile, MacroCallKind, MacroFileId, MacroFileIdExt,
+    InFile, MacroCallKind, MacroFileId, MacroFileIdExt, MacroKind,
 };
 use intern::Symbol;
 use itertools::Itertools;
@@ -211,7 +211,11 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
 
         if let Some(src) = src {
             if let Some(file_id) = src.file_id.macro_file() {
-                if file_id.is_attr_macro(&db) || file_id.is_custom_derive(&db) {
+                if let MacroKind::Derive
+                | MacroKind::DeriveBuiltIn
+                | MacroKind::Attr
+                | MacroKind::AttrBuiltIn = file_id.kind(&db)
+                {
                     let call = file_id.call_node(&db);
                     let mut show_spans = false;
                     let mut show_ctxt = false;
@@ -236,7 +240,7 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
     for impl_id in def_map[local_id].scope.impls() {
         let src = impl_id.lookup(&db).source(&db);
         if let Some(macro_file) = src.file_id.macro_file() {
-            if macro_file.is_builtin_derive(&db) {
+            if let MacroKind::DeriveBuiltIn | MacroKind::Derive = macro_file.kind(&db) {
                 let pp = pretty_print_macro_expansion(
                     src.value.syntax().clone(),
                     db.span_map(macro_file.into()).as_ref(),
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs
index afee42ecec0..17d09bcbd04 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs
@@ -134,7 +134,7 @@ impl DirPath {
     /// So this is the case which doesn't really work I think if we try to be
     /// 100% platform agnostic:
     ///
-    /// ```
+    /// ```ignore
     /// mod a {
     ///     #[path="C://sad/face"]
     ///     mod b { mod c; }
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 9dfb6e3cc4b..e5774b48044 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
@@ -532,16 +532,17 @@ impl Resolver {
     /// Note that in Rust one name can be bound to several items:
     ///
     /// ```
+    /// # #![allow(non_camel_case_types)]
     /// macro_rules! t { () => (()) }
     /// type t = t!();
-    /// const t: t = t!()
+    /// const t: t = t!();
     /// ```
     ///
     /// That's why we return a multimap.
     ///
     /// The shadowing is accounted for: in
     ///
-    /// ```
+    /// ```ignore
     /// let it = 92;
     /// {
     ///     let it = 92;
diff --git a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml
index b193a34a01d..7d561e0527d 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 cov-mark = "2.0.0-pre.1"
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 f250620e775..e9dc17a28f6 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
@@ -101,7 +101,7 @@ fn dummy_gate_test_expand(
 /// somewhat inconsistently resolve derive attributes.
 ///
 /// As such, we expand `#[derive(Foo, bar::Bar)]` into
-/// ```
+/// ```ignore
 ///  #![Foo]
 ///  #![bar::Bar]
 /// ```
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs
index 13ddb0d4acc..f3bcc772682 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs
@@ -10,7 +10,7 @@ use syntax::{AstNode, AstPtr, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange,
 
 use crate::{
     db::{self, ExpandDatabase},
-    map_node_range_up, map_node_range_up_rooted, span_for_offset, MacroFileIdExt,
+    map_node_range_up, map_node_range_up_rooted, span_for_offset, MacroFileIdExt, MacroKind,
 };
 
 /// `InFile<T>` stores a value of `T` inside a particular file/syntax tree.
@@ -276,7 +276,11 @@ impl<SN: Borrow<SyntaxNode>> InFile<SN> {
             HirFileIdRepr::FileId(file_id) => {
                 return Some(InRealFile { file_id, value: self.value.borrow().clone() })
             }
-            HirFileIdRepr::MacroFile(m) if m.is_attr_macro(db) => m,
+            HirFileIdRepr::MacroFile(m)
+                if matches!(m.kind(db), MacroKind::Attr | MacroKind::AttrBuiltIn) =>
+            {
+                m
+            }
             _ => return None,
         };
 
@@ -453,7 +457,7 @@ impl<N: AstNode> InFile<N> {
             }
             HirFileIdRepr::MacroFile(m) => m,
         };
-        if !file_id.is_attr_macro(db) {
+        if !matches!(file_id.kind(db), MacroKind::Attr | MacroKind::AttrBuiltIn) {
             return None;
         }
 
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 2c664029f61..41603e3c92e 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
@@ -416,6 +416,24 @@ impl HirFileIdExt for HirFileId {
     }
 }
 
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum MacroKind {
+    /// `macro_rules!` or Macros 2.0 macro.
+    Declarative,
+    /// A built-in function-like macro.
+    DeclarativeBuiltIn,
+    /// A custom derive.
+    Derive,
+    /// A builtin-in derive.
+    DeriveBuiltIn,
+    /// A procedural attribute macro.
+    Attr,
+    /// A built-in attribute macro.
+    AttrBuiltIn,
+    /// A function-like procedural macro.
+    ProcMacro,
+}
+
 pub trait MacroFileIdExt {
     fn is_env_or_option_env(&self, db: &dyn ExpandDatabase) -> bool;
     fn is_include_like_macro(&self, db: &dyn ExpandDatabase) -> bool;
@@ -427,15 +445,12 @@ pub trait MacroFileIdExt {
 
     fn expansion_info(self, db: &dyn ExpandDatabase) -> ExpansionInfo;
 
-    fn is_builtin_derive(&self, db: &dyn ExpandDatabase) -> bool;
-    fn is_custom_derive(&self, db: &dyn ExpandDatabase) -> bool;
+    fn kind(&self, db: &dyn ExpandDatabase) -> MacroKind;
 
     /// Return whether this file is an include macro
     fn is_include_macro(&self, db: &dyn ExpandDatabase) -> bool;
 
     fn is_eager(&self, db: &dyn ExpandDatabase) -> bool;
-    /// Return whether this file is an attr macro
-    fn is_attr_macro(&self, db: &dyn ExpandDatabase) -> bool;
 
     /// Return whether this file is the pseudo expansion of the derive attribute.
     /// See [`crate::builtin_attr_macro::derive_attr_expand`].
@@ -468,18 +483,18 @@ impl MacroFileIdExt for MacroFileId {
         ExpansionInfo::new(db, self)
     }
 
-    fn is_custom_derive(&self, db: &dyn ExpandDatabase) -> bool {
-        matches!(
-            db.lookup_intern_macro_call(self.macro_call_id).def.kind,
-            MacroDefKind::ProcMacro(_, _, ProcMacroKind::CustomDerive)
-        )
-    }
-
-    fn is_builtin_derive(&self, db: &dyn ExpandDatabase) -> bool {
-        matches!(
-            db.lookup_intern_macro_call(self.macro_call_id).def.kind,
-            MacroDefKind::BuiltInDerive(..)
-        )
+    fn kind(&self, db: &dyn ExpandDatabase) -> MacroKind {
+        match db.lookup_intern_macro_call(self.macro_call_id).def.kind {
+            MacroDefKind::Declarative(..) => MacroKind::Declarative,
+            MacroDefKind::BuiltIn(..) | MacroDefKind::BuiltInEager(..) => {
+                MacroKind::DeclarativeBuiltIn
+            }
+            MacroDefKind::BuiltInDerive(..) => MacroKind::DeriveBuiltIn,
+            MacroDefKind::ProcMacro(_, _, ProcMacroKind::CustomDerive) => MacroKind::Derive,
+            MacroDefKind::ProcMacro(_, _, ProcMacroKind::Attr) => MacroKind::Attr,
+            MacroDefKind::ProcMacro(_, _, ProcMacroKind::Bang) => MacroKind::ProcMacro,
+            MacroDefKind::BuiltInAttr(..) => MacroKind::AttrBuiltIn,
+        }
     }
 
     fn is_include_macro(&self, db: &dyn ExpandDatabase) -> bool {
@@ -507,13 +522,6 @@ impl MacroFileIdExt for MacroFileId {
         }
     }
 
-    fn is_attr_macro(&self, db: &dyn ExpandDatabase) -> bool {
-        matches!(
-            db.lookup_intern_macro_call(self.macro_call_id).def.kind,
-            MacroDefKind::BuiltInAttr(..) | MacroDefKind::ProcMacro(_, _, ProcMacroKind::Attr)
-        )
-    }
-
     fn is_derive_attr_pseudo_expansion(&self, db: &dyn ExpandDatabase) -> bool {
         let loc = db.lookup_intern_macro_call(self.macro_call_id);
         loc.def.is_attribute_derive()
diff --git a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
index 4d36de0b383..27849f3b449 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 cov-mark = "2.0.0-pre.1"
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs
index c1ac7ae173b..ee375d60deb 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests/intrinsics.rs
@@ -354,12 +354,43 @@ fn overflowing_add() {
 fn needs_drop() {
     check_number(
         r#"
-        //- minicore: copy, sized
+        //- minicore: drop, manually_drop, copy, sized
+        use core::mem::ManuallyDrop;
         extern "rust-intrinsic" {
             pub fn needs_drop<T: ?Sized>() -> bool;
         }
         struct X;
-        const GOAL: bool = !needs_drop::<i32>() && needs_drop::<X>();
+        struct NeedsDrop;
+        impl Drop for NeedsDrop {
+            fn drop(&mut self) {}
+        }
+        enum Enum<T> {
+            A(T),
+            B(X),
+        }
+        const fn val_needs_drop<T>(_v: T) -> bool { needs_drop::<T>() }
+        const fn closure_needs_drop() -> bool {
+            let a = NeedsDrop;
+            let b = X;
+            !val_needs_drop(|| &a) && val_needs_drop(move || &a) && !val_needs_drop(move || &b)
+        }
+        const fn opaque() -> impl Sized {
+            || {}
+        }
+        const fn opaque_copy() -> impl Sized + Copy {
+            || {}
+        }
+        trait Everything {}
+        impl<T> Everything for T {}
+        const GOAL: bool = !needs_drop::<i32>() && !needs_drop::<X>()
+            && needs_drop::<NeedsDrop>() && !needs_drop::<ManuallyDrop<NeedsDrop>>()
+            && needs_drop::<[NeedsDrop; 1]>() && !needs_drop::<[NeedsDrop; 0]>()
+            && needs_drop::<(X, NeedsDrop)>()
+            && needs_drop::<Enum<NeedsDrop>>() && !needs_drop::<Enum<X>>()
+            && closure_needs_drop()
+            && !val_needs_drop(opaque()) && !val_needs_drop(opaque_copy())
+            && needs_drop::<[NeedsDrop]>() && needs_drop::<dyn Everything>()
+            && !needs_drop::<&dyn Everything>() && !needs_drop::<str>();
         "#,
         1,
     );
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 6b056826670..76031491d9a 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
@@ -13,6 +13,7 @@ use hir_def::{
     ConstParamId, DefWithBodyId, EnumVariantId, FunctionId, GeneralConstId, GenericDefId, ImplId,
     LifetimeParamId, LocalFieldId, StaticId, TraitId, TypeAliasId, TypeOrConstParamId, VariantId,
 };
+use hir_expand::name::Name;
 use la_arena::ArenaMap;
 use smallvec::SmallVec;
 use triomphe::Arc;
@@ -20,6 +21,7 @@ use triomphe::Arc;
 use crate::{
     chalk_db,
     consteval::ConstEvalError,
+    drop::DropGlue,
     dyn_compatibility::DynCompatibilityViolation,
     layout::{Layout, LayoutError},
     lower::{Diagnostics, GenericDefaults, GenericPredicates},
@@ -28,7 +30,6 @@ use crate::{
     Binders, ClosureId, Const, FnDefId, ImplTraitId, ImplTraits, InferenceResult, Interner,
     PolyFnSig, Substitution, TraitEnvironment, TraitRef, Ty, TyDefId, ValueTyDefId,
 };
-use hir_expand::name::Name;
 
 #[ra_salsa::query_group(HirDatabaseStorage)]
 pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
@@ -305,6 +306,10 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
         block: Option<BlockId>,
         env: chalk_ir::Environment<Interner>,
     ) -> chalk_ir::ProgramClauses<Interner>;
+
+    #[ra_salsa::invoke(crate::drop::has_drop_glue)]
+    #[ra_salsa::cycle(crate::drop::has_drop_glue_recover)]
+    fn has_drop_glue(&self, ty: Ty, env: Arc<TraitEnvironment>) -> DropGlue {}
 }
 
 #[test]
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 ae8fbe2ce6d..49f061813d1 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -95,7 +95,7 @@ pub struct HirFormatter<'a> {
 enum BoundsFormattingCtx {
     Entered {
         /// We can have recursive bounds like the following case:
-        /// ```rust
+        /// ```ignore
         /// where
         ///     T: Foo,
         ///     T::FooAssoc: Baz<<T::FooAssoc as Bar>::BarAssoc> + Bar
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs b/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs
new file mode 100644
index 00000000000..351926c86c4
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs
@@ -0,0 +1,209 @@
+//! Utilities for computing drop info about types.
+
+use base_db::ra_salsa;
+use chalk_ir::cast::Cast;
+use hir_def::data::adt::StructFlags;
+use hir_def::lang_item::LangItem;
+use hir_def::AdtId;
+use stdx::never;
+use triomphe::Arc;
+
+use crate::{
+    db::HirDatabase, method_resolution::TyFingerprint, AliasTy, Canonical, CanonicalVarKinds,
+    InEnvironment, Interner, ProjectionTy, TraitEnvironment, Ty, TyBuilder, TyKind,
+};
+use crate::{ConcreteConst, ConstScalar, ConstValue};
+
+fn has_destructor(db: &dyn HirDatabase, adt: AdtId) -> bool {
+    let module = match adt {
+        AdtId::EnumId(id) => db.lookup_intern_enum(id).container,
+        AdtId::StructId(id) => db.lookup_intern_struct(id).container,
+        AdtId::UnionId(id) => db.lookup_intern_union(id).container,
+    };
+    let Some(drop_trait) =
+        db.lang_item(module.krate(), LangItem::Drop).and_then(|it| it.as_trait())
+    else {
+        return false;
+    };
+    let impls = match module.containing_block() {
+        Some(block) => match db.trait_impls_in_block(block) {
+            Some(it) => it,
+            None => return false,
+        },
+        None => db.trait_impls_in_crate(module.krate()),
+    };
+    let result = impls.for_trait_and_self_ty(drop_trait, TyFingerprint::Adt(adt)).next().is_some();
+    result
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
+pub enum DropGlue {
+    // Order of variants is important.
+    None,
+    /// May have a drop glue if some type parameter has it.
+    ///
+    /// For the compiler this is considered as a positive result, IDE distinguishes this from "yes".
+    DependOnParams,
+    HasDropGlue,
+}
+
+pub(crate) fn has_drop_glue(db: &dyn HirDatabase, ty: Ty, env: Arc<TraitEnvironment>) -> DropGlue {
+    match ty.kind(Interner) {
+        TyKind::Adt(adt, subst) => {
+            if has_destructor(db, adt.0) {
+                return DropGlue::HasDropGlue;
+            }
+            match adt.0 {
+                AdtId::StructId(id) => {
+                    if db.struct_data(id).flags.contains(StructFlags::IS_MANUALLY_DROP) {
+                        return DropGlue::None;
+                    }
+                    db.field_types(id.into())
+                        .iter()
+                        .map(|(_, field_ty)| {
+                            db.has_drop_glue(
+                                field_ty.clone().substitute(Interner, subst),
+                                env.clone(),
+                            )
+                        })
+                        .max()
+                        .unwrap_or(DropGlue::None)
+                }
+                // Unions cannot have fields with destructors.
+                AdtId::UnionId(_) => DropGlue::None,
+                AdtId::EnumId(id) => db
+                    .enum_data(id)
+                    .variants
+                    .iter()
+                    .map(|&(variant, _)| {
+                        db.field_types(variant.into())
+                            .iter()
+                            .map(|(_, field_ty)| {
+                                db.has_drop_glue(
+                                    field_ty.clone().substitute(Interner, subst),
+                                    env.clone(),
+                                )
+                            })
+                            .max()
+                            .unwrap_or(DropGlue::None)
+                    })
+                    .max()
+                    .unwrap_or(DropGlue::None),
+            }
+        }
+        TyKind::Tuple(_, subst) => subst
+            .iter(Interner)
+            .map(|ty| ty.assert_ty_ref(Interner))
+            .map(|ty| db.has_drop_glue(ty.clone(), env.clone()))
+            .max()
+            .unwrap_or(DropGlue::None),
+        TyKind::Array(ty, len) => {
+            if let ConstValue::Concrete(ConcreteConst { interned: ConstScalar::Bytes(len, _) }) =
+                &len.data(Interner).value
+            {
+                match (&**len).try_into() {
+                    Ok(len) => {
+                        let len = usize::from_le_bytes(len);
+                        if len == 0 {
+                            // Arrays of size 0 don't have drop glue.
+                            return DropGlue::None;
+                        }
+                    }
+                    Err(_) => {
+                        never!("const array size with non-usize len");
+                    }
+                }
+            }
+            db.has_drop_glue(ty.clone(), env)
+        }
+        TyKind::Slice(ty) => db.has_drop_glue(ty.clone(), env),
+        TyKind::Closure(closure_id, subst) => {
+            let owner = db.lookup_intern_closure((*closure_id).into()).0;
+            let infer = db.infer(owner);
+            let (captures, _) = infer.closure_info(closure_id);
+            let env = db.trait_environment_for_body(owner);
+            captures
+                .iter()
+                .map(|capture| db.has_drop_glue(capture.ty(subst), env.clone()))
+                .max()
+                .unwrap_or(DropGlue::None)
+        }
+        // FIXME: Handle coroutines.
+        TyKind::Coroutine(..) | TyKind::CoroutineWitness(..) => DropGlue::None,
+        TyKind::Ref(..)
+        | TyKind::Raw(..)
+        | TyKind::FnDef(..)
+        | TyKind::Str
+        | TyKind::Never
+        | TyKind::Scalar(_)
+        | TyKind::Function(_)
+        | TyKind::Foreign(_)
+        | TyKind::Error => DropGlue::None,
+        TyKind::Dyn(_) => DropGlue::HasDropGlue,
+        TyKind::AssociatedType(assoc_type_id, subst) => projection_has_drop_glue(
+            db,
+            env,
+            ProjectionTy { associated_ty_id: *assoc_type_id, substitution: subst.clone() },
+            ty,
+        ),
+        TyKind::Alias(AliasTy::Projection(projection)) => {
+            projection_has_drop_glue(db, env, projection.clone(), ty)
+        }
+        TyKind::OpaqueType(..) | TyKind::Alias(AliasTy::Opaque(_)) => {
+            if is_copy(db, ty, env) {
+                DropGlue::None
+            } else {
+                DropGlue::HasDropGlue
+            }
+        }
+        TyKind::Placeholder(_) | TyKind::BoundVar(_) => {
+            if is_copy(db, ty, env) {
+                DropGlue::None
+            } else {
+                DropGlue::DependOnParams
+            }
+        }
+        TyKind::InferenceVar(..) => unreachable!("inference vars shouldn't exist out of inference"),
+    }
+}
+
+fn projection_has_drop_glue(
+    db: &dyn HirDatabase,
+    env: Arc<TraitEnvironment>,
+    projection: ProjectionTy,
+    ty: Ty,
+) -> DropGlue {
+    let normalized = db.normalize_projection(projection, env.clone());
+    match normalized.kind(Interner) {
+        TyKind::Alias(AliasTy::Projection(_)) | TyKind::AssociatedType(..) => {
+            if is_copy(db, ty, env) {
+                DropGlue::None
+            } else {
+                DropGlue::DependOnParams
+            }
+        }
+        _ => db.has_drop_glue(normalized, env),
+    }
+}
+
+fn is_copy(db: &dyn HirDatabase, ty: Ty, env: Arc<TraitEnvironment>) -> bool {
+    let Some(copy_trait) = db.lang_item(env.krate, LangItem::Copy).and_then(|it| it.as_trait())
+    else {
+        return false;
+    };
+    let trait_ref = TyBuilder::trait_ref(db, copy_trait).push(ty).build();
+    let goal = Canonical {
+        value: InEnvironment::new(&env.env, trait_ref.cast(Interner)),
+        binders: CanonicalVarKinds::empty(Interner),
+    };
+    db.trait_solve(env.krate, env.block, goal).is_some()
+}
+
+pub(crate) fn has_drop_glue_recover(
+    _db: &dyn HirDatabase,
+    _cycle: &ra_salsa::Cycle,
+    _ty: &Ty,
+    _env: &Arc<TraitEnvironment>,
+) -> DropGlue {
+    DropGlue::None
+}
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 0cb7002f446..556091c4046 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
@@ -335,7 +335,7 @@ impl Default for InternedStandardTypes {
 ///    sized struct to a dynamically sized one. E.g., &[i32; 4] -> &[i32] is
 ///    represented by:
 ///
-///    ```
+///    ```ignore
 ///    Deref(None) -> [i32; 4],
 ///    Borrow(AutoBorrow::Ref) -> &[i32; 4],
 ///    Unsize -> &[i32],
@@ -481,9 +481,10 @@ pub struct InferenceResult {
     /// or pattern can have multiple binding modes. For example:
     /// ```
     /// fn foo(mut slice: &[u32]) -> usize {
-    ///    slice = match slice {
-    ///        [0, rest @ ..] | rest => rest,
-    ///    };
+    ///     slice = match slice {
+    ///         [0, rest @ ..] | rest => rest,
+    ///     };
+    ///     0
     /// }
     /// ```
     /// the first `rest` has implicit `ref` binding mode, but the second `rest` binding mode is `move`.
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
index a4e49e0aa10..7af31dabe45 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
@@ -133,40 +133,22 @@ fn layout_of_simd_ty(
     env: Arc<TraitEnvironment>,
     dl: &TargetDataLayout,
 ) -> Result<Arc<Layout>, LayoutError> {
-    let fields = db.field_types(id.into());
-
-    // Supported SIMD vectors are homogeneous ADTs with at least one field:
+    // Supported SIMD vectors are homogeneous ADTs with exactly one array field:
     //
-    // * #[repr(simd)] struct S(T, T, T, T);
-    // * #[repr(simd)] struct S { it: T, y: T, z: T, w: T }
     // * #[repr(simd)] struct S([T; 4])
     //
     // where T is a primitive scalar (integer/float/pointer).
-
-    let f0_ty = match fields.iter().next() {
-        Some(it) => it.1.clone().substitute(Interner, subst),
-        None => return Err(LayoutError::InvalidSimdType),
+    let fields = db.field_types(id.into());
+    let mut fields = fields.iter();
+    let Some(TyKind::Array(e_ty, e_len)) = fields
+        .next()
+        .filter(|_| fields.next().is_none())
+        .map(|f| f.1.clone().substitute(Interner, subst).kind(Interner).clone())
+    else {
+        return Err(LayoutError::InvalidSimdType);
     };
 
-    // The element type and number of elements of the SIMD vector
-    // are obtained from:
-    //
-    // * the element type and length of the single array field, if
-    // the first field is of array type, or
-    //
-    // * the homogeneous field type and the number of fields.
-    let (e_ty, e_len, is_array) = if let TyKind::Array(e_ty, _) = f0_ty.kind(Interner) {
-        // Extract the number of elements from the layout of the array field:
-        let FieldsShape::Array { count, .. } = db.layout_of_ty(f0_ty.clone(), env.clone())?.fields
-        else {
-            return Err(LayoutError::Unknown);
-        };
-
-        (e_ty.clone(), count, true)
-    } else {
-        // First ADT field is not an array:
-        (f0_ty, fields.iter().count() as u64, false)
-    };
+    let e_len = try_const_usize(db, &e_len).ok_or(LayoutError::HasErrorConst)? as u64;
 
     // Compute the ABI of the element type:
     let e_ly = db.layout_of_ty(e_ty, env)?;
@@ -182,16 +164,9 @@ fn layout_of_simd_ty(
     let align = dl.llvmlike_vector_align(size);
     let size = size.align_to(align.abi);
 
-    // Compute the placement of the vector fields:
-    let fields = if is_array {
-        FieldsShape::Arbitrary { offsets: [Size::ZERO].into(), memory_index: [0].into() }
-    } else {
-        FieldsShape::Array { stride: e_ly.size, count: e_len }
-    };
-
     Ok(Arc::new(Layout {
         variants: Variants::Single { index: struct_variant_idx() },
-        fields,
+        fields: FieldsShape::Arbitrary { offsets: [Size::ZERO].into(), memory_index: [0].into() },
         backend_repr: BackendRepr::SimdVector { element: e_abi, count: e_len },
         largest_niche: e_ly.largest_niche,
         uninhabited: false,
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 daddcf0b242..707c4377726 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
@@ -30,11 +30,13 @@ extern crate ra_ap_rustc_hashes as rustc_hashes;
 mod builder;
 mod chalk_db;
 mod chalk_ext;
+mod drop;
 mod infer;
 mod inhabitedness;
 mod interner;
 mod lower;
 mod mapping;
+mod target_feature;
 mod tls;
 mod utils;
 
@@ -87,6 +89,7 @@ use crate::{
 pub use autoderef::autoderef;
 pub use builder::{ParamKind, TyBuilder};
 pub use chalk_ext::*;
+pub use drop::DropGlue;
 pub use infer::{
     cast::CastError,
     closure::{CaptureKind, CapturedItem},
@@ -105,10 +108,9 @@ pub use mapping::{
     to_foreign_def_id, to_placeholder_idx,
 };
 pub use method_resolution::check_orphan_rules;
+pub use target_feature::TargetFeatures;
 pub use traits::TraitEnvironment;
-pub use utils::{
-    all_super_traits, direct_super_traits, is_fn_unsafe_to_call, TargetFeatures, Unsafety,
-};
+pub use utils::{all_super_traits, direct_super_traits, is_fn_unsafe_to_call, Unsafety};
 pub use variance::Variance;
 
 pub use chalk_ir::{
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
index 38b189a517f..7d3376f56be 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
@@ -11,6 +11,7 @@ use hir_def::{
 };
 use hir_expand::name::Name;
 use intern::{sym, Symbol};
+use stdx::never;
 
 use crate::{
     error_lifetime,
@@ -20,6 +21,7 @@ use crate::{
         LangItem, Layout, Locals, Lookup, MirEvalError, MirSpan, Mutability, Result, Substitution,
         Ty, TyBuilder, TyExt,
     },
+    DropGlue,
 };
 
 mod simd;
@@ -853,7 +855,14 @@ impl Evaluator<'_> {
                         "size_of generic arg is not provided".into(),
                     ));
                 };
-                let result = !ty.clone().is_copy(self.db, locals.body.owner);
+                let result = match self.db.has_drop_glue(ty.clone(), self.trait_env.clone()) {
+                    DropGlue::HasDropGlue => true,
+                    DropGlue::None => false,
+                    DropGlue::DependOnParams => {
+                        never!("should be fully monomorphized now");
+                        true
+                    }
+                };
                 destination.write_from_bytes(self, &[u8::from(result)])
             }
             "ptr_guaranteed_cmp" => {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/target_feature.rs b/src/tools/rust-analyzer/crates/hir-ty/src/target_feature.rs
new file mode 100644
index 00000000000..fe9416c6cfc
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/target_feature.rs
@@ -0,0 +1,261 @@
+//! Stuff for handling `#[target_feature]` (needed for unsafe check).
+
+use std::sync::LazyLock;
+
+use hir_def::attr::Attrs;
+use hir_def::tt;
+use intern::{sym, Symbol};
+use rustc_hash::{FxHashMap, FxHashSet};
+
+#[derive(Debug, Default)]
+pub struct TargetFeatures {
+    pub(crate) enabled: FxHashSet<Symbol>,
+}
+
+impl TargetFeatures {
+    pub fn from_attrs(attrs: &Attrs) -> Self {
+        let mut result = TargetFeatures::from_attrs_no_implications(attrs);
+        result.expand_implications();
+        result
+    }
+
+    fn expand_implications(&mut self) {
+        let all_implications = LazyLock::force(&TARGET_FEATURE_IMPLICATIONS);
+        let mut queue = self.enabled.iter().cloned().collect::<Vec<_>>();
+        while let Some(feature) = queue.pop() {
+            if let Some(implications) = all_implications.get(&feature) {
+                for implication in implications {
+                    if self.enabled.insert(implication.clone()) {
+                        queue.push(implication.clone());
+                    }
+                }
+            }
+        }
+    }
+
+    /// Retrieves the target features from the attributes, and does not expand the target features implied by them.
+    pub(crate) fn from_attrs_no_implications(attrs: &Attrs) -> Self {
+        let enabled = attrs
+            .by_key(&sym::target_feature)
+            .tt_values()
+            .filter_map(|tt| {
+                match tt.token_trees().flat_tokens() {
+                    [
+                        tt::TokenTree::Leaf(tt::Leaf::Ident(enable_ident)),
+                        tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: '=', .. })),
+                        tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { kind: tt::LitKind::Str, symbol: features, .. })),
+                    ] if enable_ident.sym == sym::enable => Some(features),
+                    _ => None,
+                }
+            })
+            .flat_map(|features| features.as_str().split(',').map(Symbol::intern))
+            .collect();
+        Self { enabled }
+    }
+}
+
+// List of the target features each target feature implies.
+// Ideally we'd depend on rustc for this, but rustc_target doesn't compile on stable,
+// and t-compiler prefers for it to stay this way.
+
+static TARGET_FEATURE_IMPLICATIONS: LazyLock<FxHashMap<Symbol, Box<[Symbol]>>> =
+    LazyLock::new(|| {
+        let mut result = FxHashMap::<Symbol, FxHashSet<Symbol>>::default();
+        for &(feature_str, implications) in TARGET_FEATURE_IMPLICATIONS_RAW {
+            let feature = Symbol::intern(feature_str);
+            let implications = implications.iter().copied().map(Symbol::intern);
+            // Some target features appear in two archs, e.g. Arm and x86.
+            // Sometimes they contain different implications, e.g. `aes`.
+            // We should probably choose by the active arch, but for now just merge them.
+            result.entry(feature).or_default().extend(implications);
+        }
+        let mut result = result
+            .into_iter()
+            .map(|(feature, implications)| (feature, Box::from_iter(implications)))
+            .collect::<FxHashMap<_, _>>();
+        result.shrink_to_fit();
+        result
+    });
+
+// spellchecker:off
+const TARGET_FEATURE_IMPLICATIONS_RAW: &[(&str, &[&str])] = &[
+    // Arm
+    ("aes", &["neon"]),
+    ("dotprod", &["neon"]),
+    ("fp-armv8", &["vfp4"]),
+    ("fp16", &["neon"]),
+    ("i8mm", &["neon"]),
+    ("neon", &["vfp3"]),
+    ("sha2", &["neon"]),
+    ("v6", &["v5te"]),
+    ("v6k", &["v6"]),
+    ("v6t2", &["v6k", "thumb2"]),
+    ("v7", &["v6t2"]),
+    ("v8", &["v7"]),
+    ("vfp3", &["vfp2", "d32"]),
+    ("vfp4", &["vfp3"]),
+    // Aarch64
+    ("aes", &["neon"]),
+    ("dotprod", &["neon"]),
+    ("dpb2", &["dpb"]),
+    ("f32mm", &["sve"]),
+    ("f64mm", &["sve"]),
+    ("fcma", &["neon"]),
+    ("fhm", &["fp16"]),
+    ("fp16", &["neon"]),
+    ("fp8", &["faminmax", "lut", "bf16"]),
+    ("fp8dot2", &["fp8dot4"]),
+    ("fp8dot4", &["fp8fma"]),
+    ("fp8fma", &["fp8"]),
+    ("jsconv", &["neon"]),
+    ("lse128", &["lse"]),
+    ("rcpc2", &["rcpc"]),
+    ("rcpc3", &["rcpc2"]),
+    ("rdm", &["neon"]),
+    ("sha2", &["neon"]),
+    ("sha3", &["sha2"]),
+    ("sm4", &["neon"]),
+    ("sme", &["bf16"]),
+    ("sme-b16b16", &["bf16", "sme2", "sve-b16b16"]),
+    ("sme-f16f16", &["sme2"]),
+    ("sme-f64f64", &["sme"]),
+    ("sme-f8f16", &["sme-f8f32"]),
+    ("sme-f8f32", &["sme2", "fp8"]),
+    ("sme-fa64", &["sme", "sve2"]),
+    ("sme-i16i64", &["sme"]),
+    ("sme2", &["sme"]),
+    ("sme2p1", &["sme2"]),
+    ("ssve-fp8dot2", &["ssve-fp8dot4"]),
+    ("ssve-fp8dot4", &["ssve-fp8fma"]),
+    ("ssve-fp8fma", &["sme2", "fp8"]),
+    ("sve", &["neon"]),
+    ("sve-b16b16", &["bf16"]),
+    ("sve2", &["sve"]),
+    ("sve2-aes", &["sve2", "aes"]),
+    ("sve2-bitperm", &["sve2"]),
+    ("sve2-sha3", &["sve2", "sha3"]),
+    ("sve2-sm4", &["sve2", "sm4"]),
+    ("sve2p1", &["sve2"]),
+    ("v8.1a", &["crc", "lse", "rdm", "pan", "lor", "vh"]),
+    ("v8.2a", &["v8.1a", "ras", "dpb"]),
+    ("v8.3a", &["v8.2a", "rcpc", "paca", "pacg", "jsconv"]),
+    ("v8.4a", &["v8.3a", "dotprod", "dit", "flagm"]),
+    ("v8.5a", &["v8.4a", "ssbs", "sb", "dpb2", "bti"]),
+    ("v8.6a", &["v8.5a", "bf16", "i8mm"]),
+    ("v8.7a", &["v8.6a", "wfxt"]),
+    ("v8.8a", &["v8.7a", "hbc", "mops"]),
+    ("v8.9a", &["v8.8a", "cssc"]),
+    ("v9.1a", &["v9a", "v8.6a"]),
+    ("v9.2a", &["v9.1a", "v8.7a"]),
+    ("v9.3a", &["v9.2a", "v8.8a"]),
+    ("v9.4a", &["v9.3a", "v8.9a"]),
+    ("v9.5a", &["v9.4a"]),
+    ("v9a", &["v8.5a", "sve2"]),
+    // x86
+    ("aes", &["sse2"]),
+    ("amx-bf16", &["amx-tile"]),
+    ("amx-complex", &["amx-tile"]),
+    ("amx-fp16", &["amx-tile"]),
+    ("amx-int8", &["amx-tile"]),
+    ("avx", &["sse4.2"]),
+    ("avx2", &["avx"]),
+    ("avx512bf16", &["avx512bw"]),
+    ("avx512bitalg", &["avx512bw"]),
+    ("avx512bw", &["avx512f"]),
+    ("avx512cd", &["avx512f"]),
+    ("avx512dq", &["avx512f"]),
+    ("avx512f", &["avx2", "fma", "f16c"]),
+    ("avx512fp16", &["avx512bw", "avx512vl", "avx512dq"]),
+    ("avx512ifma", &["avx512f"]),
+    ("avx512vbmi", &["avx512bw"]),
+    ("avx512vbmi2", &["avx512bw"]),
+    ("avx512vl", &["avx512f"]),
+    ("avx512vnni", &["avx512f"]),
+    ("avx512vp2intersect", &["avx512f"]),
+    ("avx512vpopcntdq", &["avx512f"]),
+    ("avxifma", &["avx2"]),
+    ("avxneconvert", &["avx2"]),
+    ("avxvnni", &["avx2"]),
+    ("avxvnniint16", &["avx2"]),
+    ("avxvnniint8", &["avx2"]),
+    ("f16c", &["avx"]),
+    ("fma", &["avx"]),
+    ("gfni", &["sse2"]),
+    ("kl", &["sse2"]),
+    ("pclmulqdq", &["sse2"]),
+    ("sha", &["sse2"]),
+    ("sha512", &["avx2"]),
+    ("sm3", &["avx"]),
+    ("sm4", &["avx2"]),
+    ("sse2", &["sse"]),
+    ("sse3", &["sse2"]),
+    ("sse4.1", &["ssse3"]),
+    ("sse4.2", &["sse4.1"]),
+    ("sse4a", &["sse3"]),
+    ("ssse3", &["sse3"]),
+    ("vaes", &["avx2", "aes"]),
+    ("vpclmulqdq", &["avx", "pclmulqdq"]),
+    ("widekl", &["kl"]),
+    ("xop", &[/*"fma4", */ "avx", "sse4a"]),
+    ("xsavec", &["xsave"]),
+    ("xsaveopt", &["xsave"]),
+    ("xsaves", &["xsave"]),
+    // Hexagon
+    ("hvx-length128b", &["hvx"]),
+    // PowerPC
+    ("power10-vector", &["power9-vector"]),
+    ("power8-altivec", &["altivec"]),
+    ("power8-crypto", &["power8-altivec"]),
+    ("power8-vector", &["vsx", "power8-altivec"]),
+    ("power9-altivec", &["power8-altivec"]),
+    ("power9-vector", &["power8-vector", "power9-altivec"]),
+    ("vsx", &["altivec"]),
+    // MIPS
+    // RISC-V
+    ("a", &["zaamo", "zalrsc"]),
+    ("d", &["f"]),
+    ("zabha", &["zaamo"]),
+    ("zdinx", &["zfinx"]),
+    ("zfh", &["zfhmin"]),
+    ("zfhmin", &["f"]),
+    ("zhinx", &["zhinxmin"]),
+    ("zhinxmin", &["zfinx"]),
+    ("zk", &["zkn", "zkr", "zkt"]),
+    ("zkn", &["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"]),
+    ("zks", &["zbkb", "zbkc", "zbkx", "zksed", "zksh"]),
+    // WASM
+    ("relaxed-simd", &["simd128"]),
+    // BPF
+    ("alu32", &[]),
+    // CSKY
+    ("10e60", &["7e10"]),
+    ("2e3", &["e2"]),
+    ("3e3r2", &["3e3r1", "doloop"]),
+    ("3e3r3", &["doloop"]),
+    ("3e7", &["2e3"]),
+    ("7e10", &["3e7"]),
+    ("e1", &["elrw"]),
+    ("e2", &["e2"]),
+    ("mp", &["2e3"]),
+    ("mp1e2", &["3e7"]),
+    // LoongArch
+    ("d", &["f"]),
+    ("lasx", &["lsx"]),
+    ("lsx", &["d"]),
+    // IBM Z
+    ("nnp-assist", &["vector"]),
+    ("vector-enhancements-1", &["vector"]),
+    ("vector-enhancements-2", &["vector-enhancements-1"]),
+    ("vector-packed-decimal", &["vector"]),
+    ("vector-packed-decimal-enhancement", &["vector-packed-decimal"]),
+    ("vector-packed-decimal-enhancement-2", &["vector-packed-decimal-enhancement"]),
+    // SPARC
+    // m68k
+    ("isa-68010", &["isa-68000"]),
+    ("isa-68020", &["isa-68010"]),
+    ("isa-68030", &["isa-68020"]),
+    ("isa-68040", &["isa-68030", "isa-68882"]),
+    ("isa-68060", &["isa-68040"]),
+    ("isa-68882", &["isa-68881"]),
+];
+// spellchecker:on
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 c131e97bc4c..89d89fe2230 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
@@ -9,18 +9,16 @@ use chalk_ir::{
     DebruijnIndex,
 };
 use hir_def::{
-    attr::Attrs,
     db::DefDatabase,
     generics::{WherePredicate, WherePredicateTypeTarget},
     lang_item::LangItem,
     resolver::{HasResolver, TypeNs},
-    tt,
     type_ref::{TraitBoundModifier, TypeRef},
     EnumId, EnumVariantId, FunctionId, Lookup, OpaqueInternableThing, TraitId, TypeAliasId,
     TypeOrConstParamId,
 };
 use hir_expand::name::Name;
-use intern::{sym, Symbol};
+use intern::sym;
 use rustc_abi::TargetDataLayout;
 use rustc_hash::FxHashSet;
 use smallvec::{smallvec, SmallVec};
@@ -32,8 +30,8 @@ use crate::{
     db::HirDatabase,
     layout::{Layout, TagEncoding},
     mir::pad16,
-    ChalkTraitId, Const, ConstScalar, GenericArg, Interner, Substitution, TraitRef, TraitRefExt,
-    Ty, WhereClause,
+    ChalkTraitId, Const, ConstScalar, GenericArg, Interner, Substitution, TargetFeatures, TraitRef,
+    TraitRefExt, Ty, WhereClause,
 };
 
 pub(crate) fn fn_traits(
@@ -267,32 +265,6 @@ impl<'a> ClosureSubst<'a> {
     }
 }
 
-#[derive(Debug, Default)]
-pub struct TargetFeatures {
-    enabled: FxHashSet<Symbol>,
-}
-
-impl TargetFeatures {
-    pub fn from_attrs(attrs: &Attrs) -> Self {
-        let enabled = attrs
-            .by_key(&sym::target_feature)
-            .tt_values()
-            .filter_map(|tt| {
-                match tt.token_trees().flat_tokens() {
-                    [
-                        tt::TokenTree::Leaf(tt::Leaf::Ident(enable_ident)),
-                        tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: '=', .. })),
-                        tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { kind: tt::LitKind::Str, symbol: features, .. })),
-                    ] if enable_ident.sym == sym::enable => Some(features),
-                    _ => None,
-                }
-            })
-            .flat_map(|features| features.as_str().split(',').map(Symbol::intern))
-            .collect();
-        Self { enabled }
-    }
-}
-
 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
 pub enum Unsafety {
     Safe,
@@ -314,7 +286,8 @@ pub fn is_fn_unsafe_to_call(
 
     if data.has_target_feature() {
         // RFC 2396 <https://rust-lang.github.io/rfcs/2396-target-feature-1.1.html>.
-        let callee_target_features = TargetFeatures::from_attrs(&db.attrs(func.into()));
+        let callee_target_features =
+            TargetFeatures::from_attrs_no_implications(&db.attrs(func.into()));
         if !caller_target_features.enabled.is_superset(&callee_target_features.enabled) {
             return Unsafety::Unsafe;
         }
diff --git a/src/tools/rust-analyzer/crates/hir/Cargo.toml b/src/tools/rust-analyzer/crates/hir/Cargo.toml
index c68ff706e48..2af3c2e4c35 100644
--- a/src/tools/rust-analyzer/crates/hir/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 rustc-hash.workspace = true
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 5923a1bc30e..55448d4ae86 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -142,7 +142,7 @@ pub use {
         name::Name,
         prettify_macro_expansion,
         proc_macro::{ProcMacros, ProcMacrosBuilder},
-        tt, ExpandResult, HirFileId, HirFileIdExt, MacroFileId, MacroFileIdExt,
+        tt, ExpandResult, HirFileId, HirFileIdExt, MacroFileId, MacroFileIdExt, MacroKind,
     },
     hir_ty::{
         consteval::ConstEvalError,
@@ -152,7 +152,7 @@ pub use {
         layout::LayoutError,
         method_resolution::TyFingerprint,
         mir::{MirEvalError, MirLowerError},
-        CastError, FnAbi, PointerCast, Safety, Variance,
+        CastError, DropGlue, FnAbi, PointerCast, Safety, Variance,
     },
     // FIXME: Properly encapsulate mir
     hir_ty::{mir, Interner as ChalkTyInterner},
@@ -699,7 +699,10 @@ 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().is_some_and(|it| it.is_builtin_derive(db.upcast())) {
+            if file_id
+                .macro_file()
+                .is_some_and(|it| it.kind(db.upcast()) == MacroKind::DeriveBuiltIn)
+            {
                 // 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;
@@ -1391,6 +1394,10 @@ impl Struct {
         Type::from_def(db, self.id)
     }
 
+    pub fn ty_placeholders(self, db: &dyn HirDatabase) -> Type {
+        Type::from_def_placeholders(db, self.id)
+    }
+
     pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type {
         Type::from_value_def(db, self.id)
     }
@@ -1436,6 +1443,10 @@ impl Union {
         Type::from_def(db, self.id)
     }
 
+    pub fn ty_placeholders(self, db: &dyn HirDatabase) -> Type {
+        Type::from_def_placeholders(db, self.id)
+    }
+
     pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type {
         Type::from_value_def(db, self.id)
     }
@@ -1490,6 +1501,10 @@ impl Enum {
         Type::from_def(db, self.id)
     }
 
+    pub fn ty_placeholders(self, db: &dyn HirDatabase) -> Type {
+        Type::from_def_placeholders(db, self.id)
+    }
+
     /// The type of the enum variant bodies.
     pub fn variant_body_ty(self, db: &dyn HirDatabase) -> Type {
         Type::new_for_crate(
@@ -2929,6 +2944,10 @@ impl TypeAlias {
         Type::from_def(db, self.id)
     }
 
+    pub fn ty_placeholders(self, db: &dyn HirDatabase) -> Type {
+        Type::from_def_placeholders(db, self.id)
+    }
+
     pub fn name(self, db: &dyn HirDatabase) -> Name {
         db.type_alias_data(self.id).name.clone()
     }
@@ -3034,20 +3053,6 @@ impl BuiltinType {
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub enum MacroKind {
-    /// `macro_rules!` or Macros 2.0 macro.
-    Declarative,
-    /// A built-in or custom derive.
-    Derive,
-    /// A built-in function-like macro.
-    BuiltIn,
-    /// A procedural attribute macro.
-    Attr,
-    /// A function-like procedural macro.
-    ProcMacro,
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub struct Macro {
     pub(crate) id: MacroId,
 }
@@ -3077,15 +3082,19 @@ impl Macro {
         match self.id {
             MacroId::Macro2Id(it) => match it.lookup(db.upcast()).expander {
                 MacroExpander::Declarative => MacroKind::Declarative,
-                MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => MacroKind::BuiltIn,
-                MacroExpander::BuiltInAttr(_) => MacroKind::Attr,
-                MacroExpander::BuiltInDerive(_) => MacroKind::Derive,
+                MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => {
+                    MacroKind::DeclarativeBuiltIn
+                }
+                MacroExpander::BuiltInAttr(_) => MacroKind::AttrBuiltIn,
+                MacroExpander::BuiltInDerive(_) => MacroKind::DeriveBuiltIn,
             },
             MacroId::MacroRulesId(it) => match it.lookup(db.upcast()).expander {
                 MacroExpander::Declarative => MacroKind::Declarative,
-                MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => MacroKind::BuiltIn,
-                MacroExpander::BuiltInAttr(_) => MacroKind::Attr,
-                MacroExpander::BuiltInDerive(_) => MacroKind::Derive,
+                MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => {
+                    MacroKind::DeclarativeBuiltIn
+                }
+                MacroExpander::BuiltInAttr(_) => MacroKind::AttrBuiltIn,
+                MacroExpander::BuiltInDerive(_) => MacroKind::DeriveBuiltIn,
             },
             MacroId::ProcMacroId(it) => match it.lookup(db.upcast()).kind {
                 ProcMacroKind::CustomDerive => MacroKind::Derive,
@@ -3096,10 +3105,10 @@ impl Macro {
     }
 
     pub fn is_fn_like(&self, db: &dyn HirDatabase) -> bool {
-        match self.kind(db) {
-            MacroKind::Declarative | MacroKind::BuiltIn | MacroKind::ProcMacro => true,
-            MacroKind::Attr | MacroKind::Derive => false,
-        }
+        matches!(
+            self.kind(db),
+            MacroKind::Declarative | MacroKind::DeclarativeBuiltIn | MacroKind::ProcMacro
+        )
     }
 
     pub fn is_builtin_derive(&self, db: &dyn HirDatabase) -> bool {
@@ -3139,11 +3148,11 @@ impl Macro {
     }
 
     pub fn is_attr(&self, db: &dyn HirDatabase) -> bool {
-        matches!(self.kind(db), MacroKind::Attr)
+        matches!(self.kind(db), MacroKind::Attr | MacroKind::AttrBuiltIn)
     }
 
     pub fn is_derive(&self, db: &dyn HirDatabase) -> bool {
-        matches!(self.kind(db), MacroKind::Derive)
+        matches!(self.kind(db), MacroKind::Derive | MacroKind::DeriveBuiltIn)
     }
 }
 
@@ -4708,6 +4717,19 @@ impl Type {
         Type::new(db, def, ty.substitute(Interner, &substs))
     }
 
+    fn from_def_placeholders(db: &dyn HirDatabase, def: impl Into<TyDefId> + HasResolver) -> Type {
+        let ty = db.ty(def.into());
+        let substs = TyBuilder::placeholder_subst(
+            db,
+            match def.into() {
+                TyDefId::AdtId(it) => GenericDefId::AdtId(it),
+                TyDefId::TypeAliasId(it) => GenericDefId::TypeAliasId(it),
+                TyDefId::BuiltinType(_) => return Type::new(db, def, ty.skip_binders().clone()),
+            },
+        );
+        Type::new(db, def, ty.substitute(Interner, &substs))
+    }
+
     fn from_value_def(db: &dyn HirDatabase, def: impl Into<ValueTyDefId> + HasResolver) -> Type {
         let Some(ty) = db.value_ty(def.into()) else {
             return Type::new(db, def, TyKind::Error.intern(Interner));
@@ -5737,6 +5759,10 @@ impl Type {
         db.layout_of_ty(self.ty.clone(), self.env.clone())
             .map(|layout| Layout(layout, db.target_data_layout(self.env.krate).unwrap()))
     }
+
+    pub fn drop_glue(&self, db: &dyn HirDatabase) -> DropGlue {
+        db.has_drop_glue(self.ty.clone(), self.env.clone())
+    }
 }
 
 #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
index c9145f7d212..bb67fa63a1d 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
@@ -508,9 +508,7 @@ impl<'db> SemanticsImpl<'db> {
         })
     }
 
-    pub fn is_derive_annotated(&self, adt: &ast::Adt) -> bool {
-        let file_id = self.find_file(adt.syntax()).file_id;
-        let adt = InFile::new(file_id, adt);
+    pub fn is_derive_annotated(&self, adt: InFile<&ast::Adt>) -> bool {
         self.with_ctx(|ctx| ctx.has_derives(adt))
     }
 
@@ -551,10 +549,8 @@ impl<'db> SemanticsImpl<'db> {
         res.is_empty().not().then_some(res)
     }
 
-    pub fn is_attr_macro_call(&self, item: &ast::Item) -> bool {
-        let file_id = self.find_file(item.syntax()).file_id;
-        let src = InFile::new(file_id, item);
-        self.with_ctx(|ctx| ctx.item_to_macro_call(src).is_some())
+    pub fn is_attr_macro_call(&self, item: InFile<&ast::Item>) -> bool {
+        self.with_ctx(|ctx| ctx.item_to_macro_call(item).is_some())
     }
 
     /// Expand the macro call with a different token tree, mapping the `token_to_map` down into the
@@ -1526,8 +1522,13 @@ impl<'db> SemanticsImpl<'db> {
         self.analyze(field.syntax())?.resolve_record_pat_field(self.db, field)
     }
 
+    // FIXME: Replace this with `resolve_macro_call2`
     pub fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<Macro> {
         let macro_call = self.find_file(macro_call.syntax()).with_value(macro_call);
+        self.resolve_macro_call2(macro_call)
+    }
+
+    pub fn resolve_macro_call2(&self, macro_call: InFile<&ast::MacroCall>) -> Option<Macro> {
         self.with_ctx(|ctx| {
             ctx.macro_call_to_macro_call(macro_call)
                 .and_then(|call| macro_call_to_macro_id(ctx, call))
@@ -1538,8 +1539,8 @@ impl<'db> SemanticsImpl<'db> {
         })
     }
 
-    pub fn is_proc_macro_call(&self, macro_call: &ast::MacroCall) -> bool {
-        self.resolve_macro_call(macro_call)
+    pub fn is_proc_macro_call(&self, macro_call: InFile<&ast::MacroCall>) -> bool {
+        self.resolve_macro_call2(macro_call)
             .is_some_and(|m| matches!(m.id, MacroId::ProcMacroId(..)))
     }
 
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 4481b8855fd..18cbaa15aea 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
@@ -5,7 +5,7 @@
 //!
 //! This module solves the following problem:
 //!
-//!     Given a piece of syntax, find the corresponding semantic definition (def).
+//! > Given a piece of syntax, find the corresponding semantic definition (def).
 //!
 //! This problem is a part of more-or-less every IDE feature implemented. Every
 //! IDE functionality (like goto to definition), conceptually starts with a
diff --git a/src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs b/src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs
index 6ad074e8e5c..d2070f0e18b 100644
--- a/src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/term_search/expr.rs
@@ -40,7 +40,7 @@ fn mod_item_path_str(
 /// Type tree shows how can we get from set of types to some type.
 ///
 /// Consider the following code as an example
-/// ```
+/// ```ignore
 /// fn foo(x: i32, y: bool) -> Option<i32> { None }
 /// fn bar() {
 ///    let a = 1;
diff --git a/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml b/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml
index ba215868710..3768c2257ca 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 cov-mark = "2.0.0-pre.1"
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs b/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs
index 64e77b2d698..b1189f0d0b0 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/assist_context.rs
@@ -52,6 +52,10 @@ pub(crate) struct AssistContext<'a> {
     frange: FileRange,
     trimmed_range: TextRange,
     source_file: SourceFile,
+    // We cache this here to speed up things slightly
+    token_at_offset: TokenAtOffset<SyntaxToken>,
+    // We cache this here to speed up things slightly
+    covering_element: SyntaxElement,
 }
 
 impl<'a> AssistContext<'a> {
@@ -78,8 +82,18 @@ impl<'a> AssistContext<'a> {
             // Selection solely consists of whitespace so just fall back to the original
             _ => frange.range,
         };
-
-        AssistContext { config, sema, frange, source_file, trimmed_range }
+        let token_at_offset = source_file.syntax().token_at_offset(frange.range.start());
+        let covering_element = source_file.syntax().covering_element(trimmed_range);
+
+        AssistContext {
+            config,
+            sema,
+            frange,
+            source_file,
+            trimmed_range,
+            token_at_offset,
+            covering_element,
+        }
     }
 
     pub(crate) fn db(&self) -> &RootDatabase {
@@ -114,7 +128,7 @@ impl<'a> AssistContext<'a> {
     }
 
     pub(crate) fn token_at_offset(&self) -> TokenAtOffset<SyntaxToken> {
-        self.source_file.syntax().token_at_offset(self.offset())
+        self.token_at_offset.clone()
     }
     pub(crate) fn find_token_syntax_at_offset(&self, kind: SyntaxKind) -> Option<SyntaxToken> {
         self.token_at_offset().find(|it| it.kind() == kind)
@@ -136,7 +150,7 @@ impl<'a> AssistContext<'a> {
     }
     /// Returns the element covered by the selection range, this excludes trailing whitespace in the selection.
     pub(crate) fn covering_element(&self) -> SyntaxElement {
-        self.source_file.syntax().covering_element(self.selection_trimmed())
+        self.covering_element.clone()
     }
 }
 
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 4a9e2256e9b..37f5f44dfa0 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
@@ -76,6 +76,8 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
 
     let cfg = ctx.config.import_path_config();
 
+    let make = SyntaxFactory::new();
+
     let module = ctx.sema.scope(expr.syntax())?.module();
     let (mut missing_pats, is_non_exhaustive, has_hidden_variants): (
         Peekable<Box<dyn Iterator<Item = (ast::Pat, bool)>>>,
@@ -93,7 +95,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
             .into_iter()
             .filter_map(|variant| {
                 Some((
-                    build_pat(ctx, module, variant, cfg)?,
+                    build_pat(ctx, &make, module, variant, cfg)?,
                     variant.should_be_hidden(ctx.db(), module.krate()),
                 ))
             })
@@ -144,10 +146,11 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
                 let is_hidden = variants
                     .iter()
                     .any(|variant| variant.should_be_hidden(ctx.db(), module.krate()));
-                let patterns =
-                    variants.into_iter().filter_map(|variant| build_pat(ctx, module, variant, cfg));
+                let patterns = variants
+                    .into_iter()
+                    .filter_map(|variant| build_pat(ctx, &make, module, variant, cfg));
 
-                (ast::Pat::from(make::tuple_pat(patterns)), is_hidden)
+                (ast::Pat::from(make.tuple_pat(patterns)), is_hidden)
             })
             .filter(|(variant_pat, _)| is_variant_missing(&top_lvl_pats, variant_pat));
         (
@@ -176,9 +179,11 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
                 let is_hidden = variants
                     .iter()
                     .any(|variant| variant.should_be_hidden(ctx.db(), module.krate()));
-                let patterns =
-                    variants.into_iter().filter_map(|variant| build_pat(ctx, module, variant, cfg));
-                (ast::Pat::from(make::slice_pat(patterns)), is_hidden)
+                let patterns = variants
+                    .into_iter()
+                    .filter_map(|variant| build_pat(ctx, &make, module, variant, cfg));
+
+                (ast::Pat::from(make.slice_pat(patterns)), is_hidden)
             })
             .filter(|(variant_pat, _)| is_variant_missing(&top_lvl_pats, variant_pat));
         (
@@ -203,8 +208,6 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
         "Fill match arms",
         ctx.sema.original_range(match_expr.syntax()).range,
         |builder| {
-            let make = SyntaxFactory::new();
-
             // having any hidden variants means that we need a catch-all arm
             needs_catch_all_arm |= has_hidden_variants;
 
@@ -243,7 +246,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
 
             if needs_catch_all_arm && !has_catch_all_arm {
                 cov_mark::hit!(added_wildcard_pattern);
-                let arm = make.match_arm(make::wildcard_pat().into(), None, make::ext::expr_todo());
+                let arm = make.match_arm(make.wildcard_pat().into(), None, make::ext::expr_todo());
                 arms.push(arm);
             }
 
@@ -290,7 +293,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
                 }
             }
 
-            editor.add_mappings(make.finish_with_mappings());
+            editor.add_mappings(make.take());
             builder.add_file_edits(ctx.file_id(), editor);
         },
     )
@@ -445,6 +448,7 @@ fn resolve_array_of_enum_def(
 
 fn build_pat(
     ctx: &AssistContext<'_>,
+    make: &SyntaxFactory,
     module: hir::Module,
     var: ExtendedVariant,
     cfg: ImportPathConfig,
@@ -455,31 +459,32 @@ fn build_pat(
             let edition = module.krate().edition(db);
             let path = mod_path_to_ast(&module.find_path(db, ModuleDef::from(var), cfg)?, edition);
             let fields = var.fields(db);
-            let pat = match var.kind(db) {
+            let pat: ast::Pat = match var.kind(db) {
                 hir::StructKind::Tuple => {
                     let mut name_generator = suggest_name::NameGenerator::new();
                     let pats = fields.into_iter().map(|f| {
                         let name = name_generator.for_type(&f.ty(db), db, edition);
                         match name {
-                            Some(name) => make::ext::simple_ident_pat(make::name(&name)).into(),
-                            None => make::wildcard_pat().into(),
+                            Some(name) => make::ext::simple_ident_pat(make.name(&name)).into(),
+                            None => make.wildcard_pat().into(),
                         }
                     });
-                    make::tuple_struct_pat(path, pats).into()
+                    make.tuple_struct_pat(path, pats).into()
                 }
                 hir::StructKind::Record => {
-                    let pats = fields
+                    let fields = fields
                         .into_iter()
-                        .map(|f| make::name(f.name(db).as_str()))
-                        .map(|name| make::ext::simple_ident_pat(name).into());
-                    make::record_pat(path, pats).into()
+                        .map(|f| make.name_ref(f.name(db).as_str()))
+                        .map(|name_ref| make.record_pat_field_shorthand(name_ref));
+                    let fields = make.record_pat_field_list(fields, None);
+                    make.record_pat_with_fields(path, fields).into()
                 }
-                hir::StructKind::Unit => make::path_pat(path),
+                hir::StructKind::Unit => make.path_pat(path),
             };
             Some(pat)
         }
-        ExtendedVariant::True => Some(ast::Pat::from(make::literal_pat("true"))),
-        ExtendedVariant::False => Some(ast::Pat::from(make::literal_pat("false"))),
+        ExtendedVariant::True => Some(ast::Pat::from(make.literal_pat("true"))),
+        ExtendedVariant::False => Some(ast::Pat::from(make.literal_pat("false"))),
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs
index 491727a30a8..77562c588e2 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs
@@ -3,12 +3,19 @@ use std::collections::VecDeque;
 use ide_db::{
     assists::GroupLabel,
     famous_defs::FamousDefs,
-    source_change::SourceChangeBuilder,
     syntax_helpers::node_ext::{for_each_tail_expr, walk_expr},
 };
 use syntax::{
-    ast::{self, make, AstNode, Expr::BinExpr, HasArgList},
-    ted, SyntaxKind, T,
+    ast::{
+        self,
+        prec::{precedence, ExprPrecedence},
+        syntax_factory::SyntaxFactory,
+        AstNode,
+        Expr::BinExpr,
+        HasArgList,
+    },
+    syntax_editor::{Position, SyntaxEditor},
+    SyntaxKind, T,
 };
 
 use crate::{utils::invert_boolean_expression, AssistContext, AssistId, AssistKind, Assists};
@@ -52,53 +59,60 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
     }
 
     let op = bin_expr.op_kind()?;
-    let inv_token = match op {
-        ast::BinaryOp::LogicOp(ast::LogicOp::And) => SyntaxKind::PIPE2,
-        ast::BinaryOp::LogicOp(ast::LogicOp::Or) => SyntaxKind::AMP2,
+    let (inv_token, prec) = match op {
+        ast::BinaryOp::LogicOp(ast::LogicOp::And) => (SyntaxKind::PIPE2, ExprPrecedence::LOr),
+        ast::BinaryOp::LogicOp(ast::LogicOp::Or) => (SyntaxKind::AMP2, ExprPrecedence::LAnd),
         _ => return None,
     };
 
-    let demorganed = bin_expr.clone_subtree().clone_for_update();
+    let make = SyntaxFactory::new();
+
+    let demorganed = bin_expr.clone_subtree();
+    let mut editor = SyntaxEditor::new(demorganed.syntax().clone());
+    editor.replace(demorganed.op_token()?, make.token(inv_token));
 
-    ted::replace(demorganed.op_token()?, ast::make::token(inv_token));
     let mut exprs = VecDeque::from([
-        (bin_expr.lhs()?, demorganed.lhs()?),
-        (bin_expr.rhs()?, demorganed.rhs()?),
+        (bin_expr.lhs()?, demorganed.lhs()?, prec),
+        (bin_expr.rhs()?, demorganed.rhs()?, prec),
     ]);
 
-    while let Some((expr, dm)) = exprs.pop_front() {
+    while let Some((expr, demorganed, prec)) = exprs.pop_front() {
         if let BinExpr(bin_expr) = &expr {
-            if let BinExpr(cbin_expr) = &dm {
+            if let BinExpr(cbin_expr) = &demorganed {
                 if op == bin_expr.op_kind()? {
-                    ted::replace(cbin_expr.op_token()?, ast::make::token(inv_token));
-                    exprs.push_back((bin_expr.lhs()?, cbin_expr.lhs()?));
-                    exprs.push_back((bin_expr.rhs()?, cbin_expr.rhs()?));
+                    editor.replace(cbin_expr.op_token()?, make.token(inv_token));
+                    exprs.push_back((bin_expr.lhs()?, cbin_expr.lhs()?, prec));
+                    exprs.push_back((bin_expr.rhs()?, cbin_expr.rhs()?, prec));
                 } else {
-                    let mut inv = invert_boolean_expression(expr);
-                    if inv.needs_parens_in(dm.syntax().parent()?) {
-                        inv = ast::make::expr_paren(inv).clone_for_update();
+                    let mut inv = invert_boolean_expression(&make, expr);
+                    if precedence(&inv).needs_parentheses_in(prec) {
+                        inv = make.expr_paren(inv).into();
                     }
-                    ted::replace(dm.syntax(), inv.syntax());
+                    editor.replace(demorganed.syntax(), inv.syntax());
                 }
             } else {
                 return None;
             }
         } else {
-            let mut inv = invert_boolean_expression(dm.clone_subtree()).clone_for_update();
-            if inv.needs_parens_in(dm.syntax().parent()?) {
-                inv = ast::make::expr_paren(inv).clone_for_update();
+            let mut inv = invert_boolean_expression(&make, demorganed.clone());
+            if precedence(&inv).needs_parentheses_in(prec) {
+                inv = make.expr_paren(inv).into();
             }
-            ted::replace(dm.syntax(), inv.syntax());
+            editor.replace(demorganed.syntax(), inv.syntax());
         }
     }
 
+    editor.add_mappings(make.finish_with_mappings());
+    let edit = editor.finish();
+    let demorganed = ast::Expr::cast(edit.new_root().clone())?;
+
     acc.add_group(
         &GroupLabel("Apply De Morgan's law".to_owned()),
         AssistId("apply_demorgan", AssistKind::RefactorRewrite),
         "Apply De Morgan's law",
         op_range,
-        |edit| {
-            let demorganed = ast::Expr::BinExpr(demorganed);
+        |builder| {
+            let make = SyntaxFactory::new();
             let paren_expr = bin_expr.syntax().parent().and_then(ast::ParenExpr::cast);
             let neg_expr = paren_expr
                 .clone()
@@ -107,24 +121,32 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
                 .filter(|prefix_expr| matches!(prefix_expr.op_kind(), Some(ast::UnaryOp::Not)))
                 .map(ast::Expr::PrefixExpr);
 
+            let mut editor;
             if let Some(paren_expr) = paren_expr {
                 if let Some(neg_expr) = neg_expr {
                     cov_mark::hit!(demorgan_double_negation);
                     let parent = neg_expr.syntax().parent();
+                    editor = builder.make_editor(neg_expr.syntax());
 
-                    if parent.is_some_and(|parent| demorganed.needs_parens_in(parent)) {
+                    if parent.is_some_and(|parent| demorganed.needs_parens_in(&parent)) {
                         cov_mark::hit!(demorgan_keep_parens_for_op_precedence2);
-                        edit.replace_ast(neg_expr, make::expr_paren(demorganed));
+                        editor.replace(neg_expr.syntax(), make.expr_paren(demorganed).syntax());
                     } else {
-                        edit.replace_ast(neg_expr, demorganed);
+                        editor.replace(neg_expr.syntax(), demorganed.syntax());
                     };
                 } else {
                     cov_mark::hit!(demorgan_double_parens);
-                    edit.replace_ast(paren_expr.into(), add_bang_paren(demorganed));
+                    editor = builder.make_editor(paren_expr.syntax());
+
+                    editor.replace(paren_expr.syntax(), add_bang_paren(&make, demorganed).syntax());
                 }
             } else {
-                edit.replace_ast(bin_expr.into(), add_bang_paren(demorganed));
+                editor = builder.make_editor(bin_expr.syntax());
+                editor.replace(bin_expr.syntax(), add_bang_paren(&make, demorganed).syntax());
             }
+
+            editor.add_mappings(make.finish_with_mappings());
+            builder.add_file_edits(ctx.file_id(), editor);
         },
     )
 }
@@ -161,7 +183,7 @@ pub(crate) fn apply_demorgan_iterator(acc: &mut Assists, ctx: &AssistContext<'_>
     let (name, arg_expr) = validate_method_call_expr(ctx, &method_call)?;
 
     let ast::Expr::ClosureExpr(closure_expr) = arg_expr else { return None };
-    let closure_body = closure_expr.body()?;
+    let closure_body = closure_expr.body()?.clone_for_update();
 
     let op_range = method_call.syntax().text_range();
     let label = format!("Apply De Morgan's law to `Iterator::{}`", name.text().as_str());
@@ -170,18 +192,19 @@ pub(crate) fn apply_demorgan_iterator(acc: &mut Assists, ctx: &AssistContext<'_>
         AssistId("apply_demorgan_iterator", AssistKind::RefactorRewrite),
         label,
         op_range,
-        |edit| {
+        |builder| {
+            let make = SyntaxFactory::new();
+            let mut editor = builder.make_editor(method_call.syntax());
             // replace the method name
             let new_name = match name.text().as_str() {
-                "all" => make::name_ref("any"),
-                "any" => make::name_ref("all"),
+                "all" => make.name_ref("any"),
+                "any" => make.name_ref("all"),
                 _ => unreachable!(),
-            }
-            .clone_for_update();
-            edit.replace_ast(name, new_name);
+            };
+            editor.replace(name.syntax(), new_name.syntax());
 
             // negate all tail expressions in the closure body
-            let tail_cb = &mut |e: &_| tail_cb_impl(edit, e);
+            let tail_cb = &mut |e: &_| tail_cb_impl(&mut editor, &make, e);
             walk_expr(&closure_body, &mut |expr| {
                 if let ast::Expr::ReturnExpr(ret_expr) = expr {
                     if let Some(ret_expr_arg) = &ret_expr.expr() {
@@ -198,15 +221,15 @@ pub(crate) fn apply_demorgan_iterator(acc: &mut Assists, ctx: &AssistContext<'_>
                 .and_then(ast::PrefixExpr::cast)
                 .filter(|prefix_expr| matches!(prefix_expr.op_kind(), Some(ast::UnaryOp::Not)))
             {
-                edit.delete(
-                    prefix_expr
-                        .op_token()
-                        .expect("prefix expression always has an operator")
-                        .text_range(),
+                editor.delete(
+                    prefix_expr.op_token().expect("prefix expression always has an operator"),
                 );
             } else {
-                edit.insert(method_call.syntax().text_range().start(), "!");
+                editor.insert(Position::before(method_call.syntax()), make.token(SyntaxKind::BANG));
             }
+
+            editor.add_mappings(make.finish_with_mappings());
+            builder.add_file_edits(ctx.file_id(), editor);
         },
     )
 }
@@ -233,26 +256,26 @@ fn validate_method_call_expr(
     it_type.impls_trait(sema.db, iter_trait, &[]).then_some((name_ref, arg_expr))
 }
 
-fn tail_cb_impl(edit: &mut SourceChangeBuilder, e: &ast::Expr) {
+fn tail_cb_impl(editor: &mut SyntaxEditor, make: &SyntaxFactory, e: &ast::Expr) {
     match e {
         ast::Expr::BreakExpr(break_expr) => {
             if let Some(break_expr_arg) = break_expr.expr() {
-                for_each_tail_expr(&break_expr_arg, &mut |e| tail_cb_impl(edit, e))
+                for_each_tail_expr(&break_expr_arg, &mut |e| tail_cb_impl(editor, make, e))
             }
         }
         ast::Expr::ReturnExpr(_) => {
             // all return expressions have already been handled by the walk loop
         }
         e => {
-            let inverted_body = invert_boolean_expression(e.clone());
-            edit.replace(e.syntax().text_range(), inverted_body.syntax().text());
+            let inverted_body = invert_boolean_expression(make, e.clone());
+            editor.replace(e.syntax(), inverted_body.syntax());
         }
     }
 }
 
 /// Add bang and parentheses to the expression.
-fn add_bang_paren(expr: ast::Expr) -> ast::Expr {
-    make::expr_prefix(T![!], make::expr_paren(expr)).into()
+fn add_bang_paren(make: &SyntaxFactory, expr: ast::Expr) -> ast::Expr {
+    make.expr_prefix(T![!], make.expr_paren(expr).into()).into()
 }
 
 #[cfg(test)]
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs
index eb784cd1226..151c71c0a76 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_bool_then.rs
@@ -8,8 +8,9 @@ use ide_db::{
 };
 use itertools::Itertools;
 use syntax::{
-    ast::{self, edit::AstNodeEdit, make, HasArgList},
-    ted, AstNode, SyntaxNode,
+    ast::{self, edit::AstNodeEdit, syntax_factory::SyntaxFactory, HasArgList},
+    syntax_editor::SyntaxEditor,
+    AstNode, SyntaxNode,
 };
 
 use crate::{
@@ -76,9 +77,9 @@ pub(crate) fn convert_if_to_bool_then(acc: &mut Assists, ctx: &AssistContext<'_>
         "Convert `if` expression to `bool::then` call",
         target,
         |builder| {
-            let closure_body = closure_body.clone_for_update();
+            let closure_body = closure_body.clone_subtree();
+            let mut editor = SyntaxEditor::new(closure_body.syntax().clone());
             // Rewrite all `Some(e)` in tail position to `e`
-            let mut replacements = Vec::new();
             for_each_tail_expr(&closure_body, &mut |e| {
                 let e = match e {
                     ast::Expr::BreakExpr(e) => e.expr(),
@@ -88,12 +89,16 @@ pub(crate) fn convert_if_to_bool_then(acc: &mut Assists, ctx: &AssistContext<'_>
                 if let Some(ast::Expr::CallExpr(call)) = e {
                     if let Some(arg_list) = call.arg_list() {
                         if let Some(arg) = arg_list.args().next() {
-                            replacements.push((call.syntax().clone(), arg.syntax().clone()));
+                            editor.replace(call.syntax(), arg.syntax());
                         }
                     }
                 }
             });
-            replacements.into_iter().for_each(|(old, new)| ted::replace(old, new));
+            let edit = editor.finish();
+            let closure_body = ast::Expr::cast(edit.new_root().clone()).unwrap();
+
+            let mut editor = builder.make_editor(expr.syntax());
+            let make = SyntaxFactory::new();
             let closure_body = match closure_body {
                 ast::Expr::BlockExpr(block) => unwrap_trivial_block(block),
                 e => e,
@@ -119,11 +124,18 @@ pub(crate) fn convert_if_to_bool_then(acc: &mut Assists, ctx: &AssistContext<'_>
                     | ast::Expr::WhileExpr(_)
                     | ast::Expr::YieldExpr(_)
             );
-            let cond = if invert_cond { invert_boolean_expression(cond) } else { cond };
-            let cond = if parenthesize { make::expr_paren(cond) } else { cond };
-            let arg_list = make::arg_list(Some(make::expr_closure(None, closure_body)));
-            let mcall = make::expr_method_call(cond, make::name_ref("then"), arg_list);
-            builder.replace(target, mcall.to_string());
+            let cond = if invert_cond {
+                invert_boolean_expression(&make, cond)
+            } else {
+                cond.clone_for_update()
+            };
+            let cond = if parenthesize { make.expr_paren(cond).into() } else { cond };
+            let arg_list = make.arg_list(Some(make.expr_closure(None, closure_body).into()));
+            let mcall = make.expr_method_call(cond, make.name_ref("then"), arg_list);
+            editor.replace(expr.syntax(), mcall.syntax());
+
+            editor.add_mappings(make.finish_with_mappings());
+            builder.add_file_edits(ctx.file_id(), editor);
         },
     )
 }
@@ -173,16 +185,17 @@ pub(crate) fn convert_bool_then_to_if(acc: &mut Assists, ctx: &AssistContext<'_>
         "Convert `bool::then` call to `if`",
         target,
         |builder| {
-            let closure_body = match closure_body {
+            let mapless_make = SyntaxFactory::without_mappings();
+            let closure_body = match closure_body.reset_indent() {
                 ast::Expr::BlockExpr(block) => block,
-                e => make::block_expr(None, Some(e)),
+                e => mapless_make.block_expr(None, Some(e)),
             };
 
-            let closure_body = closure_body.clone_for_update();
+            let closure_body = closure_body.clone_subtree();
+            let mut editor = SyntaxEditor::new(closure_body.syntax().clone());
             // Wrap all tails in `Some(...)`
-            let none_path = make::expr_path(make::ext::ident_path("None"));
-            let some_path = make::expr_path(make::ext::ident_path("Some"));
-            let mut replacements = Vec::new();
+            let none_path = mapless_make.expr_path(mapless_make.ident_path("None"));
+            let some_path = mapless_make.expr_path(mapless_make.ident_path("Some"));
             for_each_tail_expr(&ast::Expr::BlockExpr(closure_body.clone()), &mut |e| {
                 let e = match e {
                     ast::Expr::BreakExpr(e) => e.expr(),
@@ -190,28 +203,37 @@ pub(crate) fn convert_bool_then_to_if(acc: &mut Assists, ctx: &AssistContext<'_>
                     _ => Some(e.clone()),
                 };
                 if let Some(expr) = e {
-                    replacements.push((
+                    editor.replace(
                         expr.syntax().clone(),
-                        make::expr_call(some_path.clone(), make::arg_list(Some(expr)))
+                        mapless_make
+                            .expr_call(some_path.clone(), mapless_make.arg_list(Some(expr)))
                             .syntax()
-                            .clone_for_update(),
-                    ));
+                            .clone(),
+                    );
                 }
             });
-            replacements.into_iter().for_each(|(old, new)| ted::replace(old, new));
+            let edit = editor.finish();
+            let closure_body = ast::BlockExpr::cast(edit.new_root().clone()).unwrap();
+
+            let mut editor = builder.make_editor(mcall.syntax());
+            let make = SyntaxFactory::new();
 
             let cond = match &receiver {
                 ast::Expr::ParenExpr(expr) => expr.expr().unwrap_or(receiver),
                 _ => receiver,
             };
-            let if_expr = make::expr_if(
-                cond,
-                closure_body.reset_indent(),
-                Some(ast::ElseBranch::Block(make::block_expr(None, Some(none_path)))),
-            )
-            .indent(mcall.indent_level());
+            let if_expr = make
+                .expr_if(
+                    cond,
+                    closure_body,
+                    Some(ast::ElseBranch::Block(make.block_expr(None, Some(none_path)))),
+                )
+                .indent(mcall.indent_level())
+                .clone_for_update();
+            editor.replace(mcall.syntax().clone(), if_expr.syntax().clone());
 
-            builder.replace(target, if_expr.to_string());
+            editor.add_mappings(make.finish_with_mappings());
+            builder.add_file_edits(ctx.file_id(), editor);
         },
     )
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs
index c7b1314c861..5a9db67a5fb 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_comment_from_or_to_doc.rs
@@ -136,7 +136,7 @@ fn comment_to_doc(acc: &mut Assists, comment: ast::Comment, style: CommentPlacem
 
 /// Not all comments are valid candidates for conversion into doc comments. For example, the
 /// comments in the code:
-/// ```rust
+/// ```ignore
 /// // Brilliant module right here
 ///
 /// // Really good right
@@ -148,7 +148,7 @@ fn comment_to_doc(acc: &mut Assists, comment: ast::Comment, style: CommentPlacem
 /// mod nice_module {}
 /// ```
 /// can be converted to doc comments. However, the comments in this example:
-/// ```rust
+/// ```ignore
 /// fn foo_bar(foo: Foo /* not bar yet */) -> Bar {
 ///     foo.into_bar()
 ///     // Nicely done
@@ -162,7 +162,7 @@ fn comment_to_doc(acc: &mut Assists, comment: ast::Comment, style: CommentPlacem
 /// are not allowed to become doc comments. Moreover, some comments _are_ allowed, but aren't common
 /// style in Rust. For example, the following comments are allowed to be doc comments, but it is not
 /// common style for them to be:
-/// ```rust
+/// ```ignore
 /// fn foo_bar(foo: Foo) -> Bar {
 ///     // this could be an inner comment with //!
 ///     foo.into_bar()
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs
index e1966d476c5..b7a77644496 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs
@@ -17,7 +17,7 @@ use syntax::{
 
 use crate::{
     assist_context::{AssistContext, Assists},
-    utils::invert_boolean_expression,
+    utils::invert_boolean_expression_legacy,
     AssistId, AssistKind,
 };
 
@@ -139,7 +139,7 @@ fn if_expr_to_guarded_return(
                     let new_expr = {
                         let then_branch =
                             make::block_expr(once(make::expr_stmt(early_expression).into()), None);
-                        let cond = invert_boolean_expression(cond_expr);
+                        let cond = invert_boolean_expression_legacy(cond_expr);
                         make::expr_if(cond, then_branch, None).indent(if_indent_level)
                     };
                     new_expr.syntax().clone_for_update()
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_while_to_loop.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_while_to_loop.rs
index 0b92beefbcd..beec64d13b6 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_while_to_loop.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_while_to_loop.rs
@@ -13,7 +13,7 @@ use syntax::{
 
 use crate::{
     assist_context::{AssistContext, Assists},
-    utils::invert_boolean_expression,
+    utils::invert_boolean_expression_legacy,
     AssistId, AssistKind,
 };
 
@@ -63,7 +63,7 @@ pub(crate) fn convert_while_to_loop(acc: &mut Assists, ctx: &AssistContext<'_>)
                 let stmts = iter::once(make::expr_stmt(if_expr.into()).into());
                 make::block_expr(stmts, None)
             } else {
-                let if_cond = invert_boolean_expression(while_cond);
+                let if_cond = invert_boolean_expression_legacy(while_cond);
                 let if_expr = make::expr_if(if_cond, break_block, None).syntax().clone().into();
                 let elements = while_body.stmt_list().map_or_else(
                     || Either::Left(iter::empty()),
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 967da41c15f..751e4a5a571 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
@@ -272,7 +272,7 @@ fn make_function_name(semantics_scope: &hir::SemanticsScope<'_>) -> ast::NameRef
 /// * We want whole node, like `loop {}`, `2 + 2`, `{ let n = 1; }` exprs.
 ///   Then we can use `ast::Expr`
 /// * We want a few statements for a block. E.g.
-///   ```rust,no_run
+///   ```ignore
 ///   fn foo() -> i32 {
 ///     let m = 1;
 ///     $0
@@ -386,7 +386,7 @@ struct ContainerInfo {
 /// Control flow that is exported from extracted function
 ///
 /// E.g.:
-/// ```rust,no_run
+/// ```ignore
 /// loop {
 ///     $0
 ///     if 42 == 42 {
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_comma.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_comma.rs
index 95e035c0537..dd27269b001 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_comma.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_comma.rs
@@ -1,8 +1,8 @@
 use syntax::{
     algo::non_trivia_sibling,
     ast::{self, syntax_factory::SyntaxFactory},
-    syntax_editor::{Element, SyntaxMapping},
-    AstNode, Direction, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxToken, T,
+    syntax_editor::SyntaxMapping,
+    AstNode, Direction, NodeOrToken, SyntaxKind, SyntaxToken, T,
 };
 
 use crate::{AssistContext, AssistId, AssistKind, Assists};
@@ -39,37 +39,24 @@ pub(crate) fn flip_comma(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<(
         return None;
     }
 
-    let prev = match prev {
-        SyntaxElement::Node(node) => node.syntax_element(),
-        _ => prev,
-    };
-    let next = match next {
-        SyntaxElement::Node(node) => node.syntax_element(),
-        _ => next,
-    };
-
-    acc.add(
-        AssistId("flip_comma", AssistKind::RefactorRewrite),
-        "Flip comma",
-        comma.text_range(),
-        |builder| {
-            let parent = comma.parent().unwrap();
-            let mut editor = builder.make_editor(&parent);
-
-            if let Some(parent) = ast::TokenTree::cast(parent) {
-                // An attribute. It often contains a path followed by a
-                // token tree (e.g. `align(2)`), so we have to be smarter.
-                let (new_tree, mapping) = flip_tree(parent.clone(), comma);
-                editor.replace(parent.syntax(), new_tree.syntax());
-                editor.add_mappings(mapping);
-            } else {
-                editor.replace(prev.clone(), next.clone());
-                editor.replace(next.clone(), prev.clone());
-            }
-
-            builder.add_file_edits(ctx.file_id(), editor);
-        },
-    )
+    let target = comma.text_range();
+    acc.add(AssistId("flip_comma", AssistKind::RefactorRewrite), "Flip comma", target, |builder| {
+        let parent = comma.parent().unwrap();
+        let mut editor = builder.make_editor(&parent);
+
+        if let Some(parent) = ast::TokenTree::cast(parent) {
+            // An attribute. It often contains a path followed by a
+            // token tree (e.g. `align(2)`), so we have to be smarter.
+            let (new_tree, mapping) = flip_tree(parent.clone(), comma);
+            editor.replace(parent.syntax(), new_tree.syntax());
+            editor.add_mappings(mapping);
+        } else {
+            editor.replace(prev.clone(), next.clone());
+            editor.replace(next.clone(), prev.clone());
+        }
+
+        builder.add_file_edits(ctx.file_id(), editor);
+    })
 }
 
 fn flip_tree(tree: ast::TokenTree, comma: SyntaxToken) -> (ast::TokenTree, SyntaxMapping) {
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_or_pattern.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_or_pattern.rs
new file mode 100644
index 00000000000..d9fa03e7191
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_or_pattern.rs
@@ -0,0 +1,80 @@
+use syntax::{
+    algo::non_trivia_sibling,
+    ast::{self, AstNode},
+    Direction, T,
+};
+
+use crate::{AssistContext, AssistId, AssistKind, Assists};
+
+// Assist: flip_or_pattern
+//
+// Flips two patterns in an or-pattern.
+//
+// ```
+// fn foo() {
+//     let (a |$0 b) = 1;
+// }
+// ```
+// ->
+// ```
+// fn foo() {
+//     let (b | a) = 1;
+// }
+// ```
+pub(crate) fn flip_or_pattern(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
+    // Only flip on the `|` token
+    let pipe = ctx.find_token_syntax_at_offset(T![|])?;
+
+    let parent = ast::OrPat::cast(pipe.parent()?)?;
+
+    let before = non_trivia_sibling(pipe.clone().into(), Direction::Prev)?.into_node()?;
+    let after = non_trivia_sibling(pipe.clone().into(), Direction::Next)?.into_node()?;
+
+    let target = pipe.text_range();
+    acc.add(
+        AssistId("flip_or_pattern", AssistKind::RefactorRewrite),
+        "Flip patterns",
+        target,
+        |builder| {
+            let mut editor = builder.make_editor(parent.syntax());
+            editor.replace(before.clone(), after.clone());
+            editor.replace(after, before);
+            builder.add_file_edits(ctx.file_id(), editor);
+        },
+    )
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
+
+    #[test]
+    fn flip_or_pattern_assist_available() {
+        check_assist_target(flip_or_pattern, "fn main(a |$0 b: ()) {}", "|")
+    }
+
+    #[test]
+    fn flip_or_pattern_not_applicable_for_leading_pipe() {
+        check_assist_not_applicable(flip_or_pattern, "fn main(|$0 b: ()) {}")
+    }
+
+    #[test]
+    fn flip_or_pattern_works() {
+        check_assist(
+            flip_or_pattern,
+            "fn foo() { let (a | b |$0 c | d) = 1; }",
+            "fn foo() { let (a | c | b | d) = 1; }",
+        )
+    }
+
+    #[test]
+    fn flip_or_pattern_works_match_guard() {
+        check_assist(
+            flip_or_pattern,
+            "fn foo() { match() { a |$0 b if true => () }}",
+            "fn foo() { match() { b | a if true => () }}",
+        )
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_trait_bound.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_trait_bound.rs
index 298e5bd82c9..3528f5e8132 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_trait_bound.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/flip_trait_bound.rs
@@ -18,17 +18,14 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
 // fn foo<T: Copy + Clone>() { }
 // ```
 pub(crate) fn flip_trait_bound(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
-    // We want to replicate the behavior of `flip_binexpr` by only suggesting
-    // the assist when the cursor is on a `+`
+    // Only flip on the `+` token
     let plus = ctx.find_token_syntax_at_offset(T![+])?;
 
     // Make sure we're in a `TypeBoundList`
     let parent = ast::TypeBoundList::cast(plus.parent()?)?;
 
-    let (before, after) = (
-        non_trivia_sibling(plus.clone().into(), Direction::Prev)?.into_node()?,
-        non_trivia_sibling(plus.clone().into(), Direction::Next)?.into_node()?,
-    );
+    let before = non_trivia_sibling(plus.clone().into(), Direction::Prev)?.into_node()?;
+    let after = non_trivia_sibling(plus.clone().into(), Direction::Next)?.into_node()?;
 
     let target = plus.text_range();
     acc.add(
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 8f5daa4125a..91e248a1de5 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
@@ -1037,7 +1037,7 @@ fn filter_bounds_in_scope(
 
 /// Makes duplicate argument names unique by appending incrementing numbers.
 ///
-/// ```
+/// ```ignore
 /// let mut names: Vec<String> =
 ///     vec!["foo".into(), "foo".into(), "bar".into(), "baz".into(), "bar".into()];
 /// deduplicate_arg_names(&mut names);
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs
index 7b7dac9a3d6..4439830947a 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs
@@ -78,7 +78,7 @@ pub(crate) fn generate_impl(acc: &mut Assists, ctx: &AssistContext<'_>) -> Optio
 //     data: T,
 // }
 //
-// impl<T: Clone> ${0:_} for Ctx<T> {}
+// impl<T: Clone> ${1:_} for Ctx<T> {$0}
 // ```
 pub(crate) fn generate_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
     let nominal = ctx.find_node_at_offset::<ast::Adt>()?;
@@ -102,6 +102,10 @@ pub(crate) fn generate_trait_impl(acc: &mut Assists, ctx: &AssistContext<'_>) ->
                 if let Some(trait_) = impl_.trait_() {
                     edit.add_placeholder_snippet(cap, trait_);
                 }
+
+                if let Some(l_curly) = impl_.assoc_item_list().and_then(|it| it.l_curly_token()) {
+                    edit.add_tabstop_after_token(cap, l_curly);
+                }
             }
 
             insert_impl(impl_, &edit.make_mut(nominal));
@@ -278,7 +282,7 @@ mod tests {
             r#"
                 struct Foo {}
 
-                impl ${0:_} for Foo {}
+                impl ${1:_} for Foo {$0}
             "#,
         );
     }
@@ -293,7 +297,7 @@ mod tests {
             r#"
                 struct Foo<T: Clone> {}
 
-                impl<T: Clone> ${0:_} for Foo<T> {}
+                impl<T: Clone> ${1:_} for Foo<T> {$0}
             "#,
         );
     }
@@ -308,7 +312,7 @@ mod tests {
             r#"
                 struct Foo<'a, T: Foo<'a>> {}
 
-                impl<'a, T: Foo<'a>> ${0:_} for Foo<'a, T> {}
+                impl<'a, T: Foo<'a>> ${1:_} for Foo<'a, T> {$0}
             "#,
         );
     }
@@ -326,7 +330,7 @@ mod tests {
                 struct Foo<'a, T: Foo<'a>> {}
 
                 #[cfg(feature = "foo")]
-                impl<'a, T: Foo<'a>> ${0:_} for Foo<'a, T> {}
+                impl<'a, T: Foo<'a>> ${1:_} for Foo<'a, T> {$0}
             "#,
         );
     }
@@ -341,7 +345,7 @@ mod tests {
             r#"
                 struct Defaulted<T = i32> {}
 
-                impl<T> ${0:_} for Defaulted<T> {}
+                impl<T> ${1:_} for Defaulted<T> {$0}
             "#,
         );
     }
@@ -356,7 +360,7 @@ mod tests {
             r#"
                 struct Defaulted<'a, 'b: 'a, T: Debug + Clone + 'a + 'b = String, const S: usize> {}
 
-                impl<'a, 'b: 'a, T: Debug + Clone + 'a + 'b, const S: usize> ${0:_} for Defaulted<'a, 'b, T, S> {}
+                impl<'a, 'b: 'a, T: Debug + Clone + 'a + 'b, const S: usize> ${1:_} for Defaulted<'a, 'b, T, S> {$0}
             "#,
         );
     }
@@ -371,7 +375,7 @@ mod tests {
             r#"
                 struct Defaulted<const N: i32 = 0> {}
 
-                impl<const N: i32> ${0:_} for Defaulted<N> {}
+                impl<const N: i32> ${1:_} for Defaulted<N> {$0}
             "#,
         );
     }
@@ -398,10 +402,10 @@ mod tests {
                     inner: T,
                 }
 
-                impl<T> ${0:_} for Struct<T>
+                impl<T> ${1:_} for Struct<T>
                 where
                     T: Trait,
-                {
+                {$0
                 }
             "#,
         );
@@ -476,7 +480,7 @@ mod tests {
                 mod foo {
                     struct Bar {}
 
-                    impl ${0:_} for Bar {}
+                    impl ${1:_} for Bar {$0}
                 }
             "#,
         );
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs
index c92c22378f8..139078eee7c 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_const_as_literal.rs
@@ -39,25 +39,10 @@ pub(crate) fn inline_const_as_literal(acc: &mut Assists, ctx: &AssistContext<'_>
         // FIXME: Add support to handle type aliases for builtin scalar types.
         validate_type_recursively(ctx, Some(&konst_ty), false, fuel)?;
 
-        let expr = konst.value(ctx.sema.db)?;
-
-        let value = match expr {
-            ast::Expr::BlockExpr(_)
-            | ast::Expr::Literal(_)
-            | ast::Expr::RefExpr(_)
-            | ast::Expr::ArrayExpr(_)
-            | ast::Expr::TupleExpr(_)
-            | ast::Expr::IfExpr(_)
-            | ast::Expr::ParenExpr(_)
-            | ast::Expr::MatchExpr(_)
-            | ast::Expr::MacroExpr(_)
-            | ast::Expr::BinExpr(_)
-            | ast::Expr::CallExpr(_) => konst
-                .eval(ctx.sema.db)
-                .ok()?
-                .render(ctx.sema.db, konst.krate(ctx.sema.db).edition(ctx.sema.db)),
-            _ => return None,
-        };
+        let value = konst
+            .eval(ctx.sema.db)
+            .ok()?
+            .render(ctx.sema.db, konst.krate(ctx.sema.db).edition(ctx.sema.db));
 
         let id = AssistId("inline_const_as_literal", AssistKind::RefactorInline);
 
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs
index b9fc075ae83..cc7bea5152b 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_local_variable.rs
@@ -73,39 +73,12 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext<'_>)
             }
             let usage_node =
                 name_ref.syntax().ancestors().find(|it| ast::PathExpr::can_cast(it.kind()));
-            let usage_parent_option =
-                usage_node.and_then(|it| it.parent()).and_then(ast::Expr::cast);
+            let usage_parent_option = usage_node.and_then(|it| it.parent());
             let usage_parent = match usage_parent_option {
                 Some(u) => u,
                 None => return Some((range, name_ref, false)),
             };
-            let initializer = matches!(
-                initializer_expr,
-                ast::Expr::CallExpr(_)
-                    | ast::Expr::IndexExpr(_)
-                    | ast::Expr::MethodCallExpr(_)
-                    | ast::Expr::FieldExpr(_)
-                    | ast::Expr::TryExpr(_)
-                    | ast::Expr::Literal(_)
-                    | ast::Expr::TupleExpr(_)
-                    | ast::Expr::ArrayExpr(_)
-                    | ast::Expr::ParenExpr(_)
-                    | ast::Expr::PathExpr(_)
-                    | ast::Expr::BlockExpr(_),
-            );
-            let parent = matches!(
-                usage_parent,
-                ast::Expr::TupleExpr(_)
-                    | ast::Expr::ArrayExpr(_)
-                    | ast::Expr::ParenExpr(_)
-                    | ast::Expr::ForExpr(_)
-                    | ast::Expr::WhileExpr(_)
-                    | ast::Expr::BreakExpr(_)
-                    | ast::Expr::ReturnExpr(_)
-                    | ast::Expr::MatchExpr(_)
-                    | ast::Expr::BlockExpr(_)
-            );
-            Some((range, name_ref, !(initializer || parent)))
+            Some((range, name_ref, initializer_expr.needs_parens_in(&usage_parent)))
         })
         .collect::<Option<Vec<_>>>()?;
 
@@ -281,11 +254,11 @@ fn foo() {
             r"
 fn bar(a: usize) {}
 fn foo() {
-    (1 + 1) + 1;
-    if (1 + 1) > 10 {
+    1 + 1 + 1;
+    if 1 + 1 > 10 {
     }
 
-    while (1 + 1) > 10 {
+    while 1 + 1 > 10 {
 
     }
     let b = (1 + 1) * 10;
@@ -350,14 +323,14 @@ fn foo() {
             r"
 fn bar(a: usize) -> usize { a }
 fn foo() {
-    (bar(1) as u64) + 1;
-    if (bar(1) as u64) > 10 {
+    bar(1) as u64 + 1;
+    if bar(1) as u64 > 10 {
     }
 
-    while (bar(1) as u64) > 10 {
+    while bar(1) as u64 > 10 {
 
     }
-    let b = (bar(1) as u64) * 10;
+    let b = bar(1) as u64 * 10;
     bar(bar(1) as u64);
 }",
         );
@@ -574,7 +547,7 @@ fn foo() {
             r"
 fn foo() {
     let bar = 10;
-    let b = (&bar) * 10;
+    let b = &bar * 10;
 }",
         );
     }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_type_alias.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_type_alias.rs
index 66dffde505c..76d465b0110 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_type_alias.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_type_alias.rs
@@ -276,7 +276,7 @@ impl ConstAndTypeMap {
 /// 1. Map the provided instance's generic args to the type alias's generic
 ///    params:
 ///
-///    ```
+///    ```ignore
 ///    type A<'a, const N: usize, T = u64> = &'a [T; N];
 ///          ^ alias generic params
 ///    let a: A<100>;
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/invert_if.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/invert_if.rs
index 547158e2977..ac710503d8a 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/invert_if.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/invert_if.rs
@@ -6,7 +6,7 @@ use syntax::{
 
 use crate::{
     assist_context::{AssistContext, Assists},
-    utils::invert_boolean_expression,
+    utils::invert_boolean_expression_legacy,
     AssistId, AssistKind,
 };
 
@@ -48,7 +48,7 @@ pub(crate) fn invert_if(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()
     };
 
     acc.add(AssistId("invert_if", AssistKind::RefactorRewrite), "Invert if", if_range, |edit| {
-        let flip_cond = invert_boolean_expression(cond.clone());
+        let flip_cond = invert_boolean_expression_legacy(cond.clone());
         edit.replace_ast(cond, flip_cond);
 
         let else_node = else_block.syntax();
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_mut.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_mut.rs
index 0b299e8349a..43740a5a6d5 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_mut.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_mut.rs
@@ -1,4 +1,4 @@
-use syntax::{SyntaxKind, TextRange, T};
+use syntax::{SyntaxKind, T};
 
 use crate::{AssistContext, AssistId, AssistKind, Assists};
 
@@ -19,11 +19,6 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
 // ```
 pub(crate) fn remove_mut(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
     let mut_token = ctx.find_token_syntax_at_offset(T![mut])?;
-    let delete_from = mut_token.text_range().start();
-    let delete_to = match mut_token.next_token() {
-        Some(it) if it.kind() == SyntaxKind::WHITESPACE => it.text_range().end(),
-        _ => mut_token.text_range().end(),
-    };
 
     let target = mut_token.text_range();
     acc.add(
@@ -31,7 +26,13 @@ pub(crate) fn remove_mut(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<(
         "Remove `mut` keyword",
         target,
         |builder| {
-            builder.delete(TextRange::new(delete_from, delete_to));
+            let mut editor = builder.make_editor(&mut_token.parent().unwrap());
+            match mut_token.next_token() {
+                Some(it) if it.kind() == SyntaxKind::WHITESPACE => editor.delete(it),
+                _ => (),
+            }
+            editor.delete(mut_token);
+            builder.add_file_edits(ctx.file_id(), editor);
         },
     )
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs
index f74fc261128..e7beb23bf8e 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_parentheses.rs
@@ -1,4 +1,8 @@
-use syntax::{ast, AstNode, SyntaxKind, T};
+use syntax::{
+    ast::{self, syntax_factory::SyntaxFactory},
+    syntax_editor::Position,
+    AstNode, SyntaxKind, T,
+};
 
 use crate::{AssistContext, AssistId, AssistKind, Assists};
 
@@ -30,7 +34,7 @@ pub(crate) fn remove_parentheses(acc: &mut Assists, ctx: &AssistContext<'_>) ->
     let expr = parens.expr()?;
 
     let parent = parens.syntax().parent()?;
-    if expr.needs_parens_in(parent) {
+    if expr.needs_parens_in(&parent) {
         return None;
     }
 
@@ -40,6 +44,7 @@ pub(crate) fn remove_parentheses(acc: &mut Assists, ctx: &AssistContext<'_>) ->
         "Remove redundant parentheses",
         target,
         |builder| {
+            let mut editor = builder.make_editor(parens.syntax());
             let prev_token = parens.syntax().first_token().and_then(|it| it.prev_token());
             let need_to_add_ws = match prev_token {
                 Some(it) => {
@@ -48,9 +53,13 @@ pub(crate) fn remove_parentheses(acc: &mut Assists, ctx: &AssistContext<'_>) ->
                 }
                 None => false,
             };
-            let expr = if need_to_add_ws { format!(" {expr}") } else { expr.to_string() };
-
-            builder.replace(parens.syntax().text_range(), expr)
+            if need_to_add_ws {
+                let make = SyntaxFactory::new();
+                editor.insert(Position::before(parens.syntax()), make.whitespace(" "));
+                editor.add_mappings(make.finish_with_mappings());
+            }
+            editor.replace(parens.syntax(), expr.syntax());
+            builder.add_file_edits(ctx.file_id(), editor);
         },
     )
 }
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 75120768da0..5ddb17b2072 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
@@ -1,8 +1,9 @@
 use ide_db::{defs::Definition, search::FileReference, EditionedFileId};
 use syntax::{
-    algo::find_node_at_range,
+    algo::{find_node_at_range, least_common_ancestor_element},
     ast::{self, HasArgList},
-    AstNode, SourceFile, SyntaxKind, SyntaxNode, TextRange, T,
+    syntax_editor::Element,
+    AstNode, SourceFile, SyntaxElement, SyntaxKind, SyntaxNode, TextRange, T,
 };
 
 use SyntaxKind::WHITESPACE;
@@ -74,15 +75,21 @@ pub(crate) fn remove_unused_param(acc: &mut Assists, ctx: &AssistContext<'_>) ->
         cov_mark::hit!(keep_used);
         return None;
     }
+    let parent = param.syntax().parent()?;
     acc.add(
         AssistId("remove_unused_param", AssistKind::Refactor),
         "Remove unused parameter",
         param.syntax().text_range(),
         |builder| {
-            builder.delete(range_to_remove(param.syntax()));
+            let mut editor = builder.make_editor(&parent);
+            let elements = elements_to_remove(param.syntax());
+            for element in elements {
+                editor.delete(element);
+            }
             for (file_id, references) in fn_def.usages(&ctx.sema).all() {
                 process_usages(ctx, builder, file_id, references, param_position, is_self_present);
             }
+            builder.add_file_edits(ctx.file_id(), editor);
         },
     )
 }
@@ -96,20 +103,24 @@ fn process_usages(
     is_self_present: bool,
 ) {
     let source_file = ctx.sema.parse(file_id);
-    builder.edit_file(file_id);
     let possible_ranges = references
         .into_iter()
         .filter_map(|usage| process_usage(&source_file, usage, arg_to_remove, is_self_present));
 
-    let mut ranges_to_delete: Vec<TextRange> = vec![];
-    for range in possible_ranges {
-        if !ranges_to_delete.iter().any(|it| it.contains_range(range)) {
-            ranges_to_delete.push(range)
+    for element_range in possible_ranges {
+        let Some(SyntaxElement::Node(parent)) = element_range
+            .iter()
+            .cloned()
+            .reduce(|a, b| least_common_ancestor_element(&a, &b).unwrap().syntax_element())
+        else {
+            continue;
+        };
+        let mut editor = builder.make_editor(&parent);
+        for element in element_range {
+            editor.delete(element);
         }
-    }
 
-    for range in ranges_to_delete {
-        builder.delete(range)
+        builder.add_file_edits(file_id, editor);
     }
 }
 
@@ -118,7 +129,7 @@ fn process_usage(
     FileReference { range, .. }: FileReference,
     mut arg_to_remove: usize,
     is_self_present: bool,
-) -> Option<TextRange> {
+) -> Option<Vec<SyntaxElement>> {
     let call_expr_opt: Option<ast::CallExpr> = find_node_at_range(source_file.syntax(), range);
     if let Some(call_expr) = call_expr_opt {
         let call_expr_range = call_expr.expr()?.syntax().text_range();
@@ -127,7 +138,7 @@ fn process_usage(
         }
 
         let arg = call_expr.arg_list()?.args().nth(arg_to_remove)?;
-        return Some(range_to_remove(arg.syntax()));
+        return Some(elements_to_remove(arg.syntax()));
     }
 
     let method_call_expr_opt: Option<ast::MethodCallExpr> =
@@ -143,7 +154,7 @@ fn process_usage(
         }
 
         let arg = method_call_expr.arg_list()?.args().nth(arg_to_remove)?;
-        return Some(range_to_remove(arg.syntax()));
+        return Some(elements_to_remove(arg.syntax()));
     }
 
     None
@@ -174,6 +185,29 @@ pub(crate) fn range_to_remove(node: &SyntaxNode) -> TextRange {
     }
 }
 
+pub(crate) fn elements_to_remove(node: &SyntaxNode) -> Vec<SyntaxElement> {
+    let up_to_comma = next_prev().find_map(|dir| {
+        node.siblings_with_tokens(dir)
+            .filter_map(|it| it.into_token())
+            .find(|it| it.kind() == T![,])
+            .map(|it| (dir, it))
+    });
+    if let Some((dir, token)) = up_to_comma {
+        let after = token.siblings_with_tokens(dir).nth(1).unwrap();
+        let mut result: Vec<_> =
+            node.siblings_with_tokens(dir).take_while(|it| it != &after).collect();
+        if node.next_sibling().is_some() {
+            result.extend(
+                token.siblings_with_tokens(dir).skip(1).take_while(|it| it.kind() == WHITESPACE),
+            );
+        }
+
+        result
+    } else {
+        vec![node.syntax_element()]
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use crate::tests::{check_assist, check_assist_not_applicable};
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs
index 0876246e90b..baf4ddae2fb 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/unqualify_method_call.rs
@@ -1,6 +1,6 @@
 use ide_db::imports::insert_use::ImportScope;
 use syntax::{
-    ast::{self, make, AstNode, HasArgList},
+    ast::{self, prec::ExprPrecedence, AstNode, HasArgList},
     TextRange,
 };
 
@@ -55,7 +55,7 @@ pub(crate) fn unqualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>)
         TextRange::new(path.syntax().text_range().start(), l_paren.text_range().end());
 
     // Parens around `expr` if needed
-    let parens = needs_parens_as_receiver(&first_arg).then(|| {
+    let parens = first_arg.precedence().needs_parentheses_in(ExprPrecedence::Postfix).then(|| {
         let range = first_arg.syntax().text_range();
         (range.start(), range.end())
     });
@@ -124,24 +124,6 @@ fn add_import(
     }
 }
 
-fn needs_parens_as_receiver(expr: &ast::Expr) -> bool {
-    // Make `(expr).dummy()`
-    let dummy_call = make::expr_method_call(
-        make::expr_paren(expr.clone()),
-        make::name_ref("dummy"),
-        make::arg_list([]),
-    );
-
-    // Get the `expr` clone with the right parent back
-    // (unreachable!s are fine since we've just constructed the expression)
-    let ast::Expr::MethodCallExpr(call) = &dummy_call else { unreachable!() };
-    let Some(receiver) = call.receiver() else { unreachable!() };
-    let ast::Expr::ParenExpr(parens) = receiver else { unreachable!() };
-    let Some(expr) = parens.expr() else { unreachable!() };
-
-    expr.needs_parens_in(dummy_call.syntax().clone())
-}
-
 #[cfg(test)]
 mod tests {
     use crate::tests::{check_assist, check_assist_not_applicable};
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
index 179742f91b4..448bcadb8ef 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/lib.rs
@@ -149,6 +149,7 @@ mod handlers {
     mod fix_visibility;
     mod flip_binexpr;
     mod flip_comma;
+    mod flip_or_pattern;
     mod flip_trait_bound;
     mod generate_constant;
     mod generate_default_from_enum_variant;
@@ -279,6 +280,7 @@ mod handlers {
             fix_visibility::fix_visibility,
             flip_binexpr::flip_binexpr,
             flip_comma::flip_comma,
+            flip_or_pattern::flip_or_pattern,
             flip_trait_bound::flip_trait_bound,
             generate_constant::generate_constant,
             generate_default_from_enum_variant::generate_default_from_enum_variant,
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 0662527a387..91c1a3e1bd7 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
@@ -1196,6 +1196,23 @@ fn main() {
 }
 
 #[test]
+fn doctest_flip_or_pattern() {
+    check_doc_test(
+        "flip_or_pattern",
+        r#####"
+fn foo() {
+    let (a |$0 b) = 1;
+}
+"#####,
+        r#####"
+fn foo() {
+    let (b | a) = 1;
+}
+"#####,
+    )
+}
+
+#[test]
 fn doctest_flip_trait_bound() {
     check_doc_test(
         "flip_trait_bound",
@@ -1961,7 +1978,7 @@ struct Ctx<T: Clone> {
     data: T,
 }
 
-impl<T: Clone> ${0:_} for Ctx<T> {}
+impl<T: Clone> ${1:_} for Ctx<T> {$0}
 "#####,
     )
 }
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 c1332d99bff..39686f065a9 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/utils.rs
@@ -17,7 +17,9 @@ use syntax::{
         self,
         edit::{AstNodeEdit, IndentLevel},
         edit_in_place::{AttrsOwnerEdit, Indent, Removable},
-        make, HasArgList, HasAttrs, HasGenericParams, HasName, HasTypeBounds, Whitespace,
+        make,
+        syntax_factory::SyntaxFactory,
+        HasArgList, HasAttrs, HasGenericParams, HasName, HasTypeBounds, Whitespace,
     },
     ted, AstNode, AstToken, Direction, Edition, NodeOrToken, SourceFile,
     SyntaxKind::*,
@@ -245,11 +247,79 @@ pub(crate) fn vis_offset(node: &SyntaxNode) -> TextSize {
         .unwrap_or_else(|| node.text_range().start())
 }
 
-pub(crate) fn invert_boolean_expression(expr: ast::Expr) -> ast::Expr {
-    invert_special_case(&expr).unwrap_or_else(|| make::expr_prefix(T![!], expr).into())
+pub(crate) fn invert_boolean_expression(make: &SyntaxFactory, expr: ast::Expr) -> ast::Expr {
+    invert_special_case(make, &expr).unwrap_or_else(|| make.expr_prefix(T![!], expr).into())
 }
 
-fn invert_special_case(expr: &ast::Expr) -> Option<ast::Expr> {
+// FIXME: Migrate usages of this function to the above function and remove this.
+pub(crate) fn invert_boolean_expression_legacy(expr: ast::Expr) -> ast::Expr {
+    invert_special_case_legacy(&expr).unwrap_or_else(|| make::expr_prefix(T![!], expr).into())
+}
+
+fn invert_special_case(make: &SyntaxFactory, expr: &ast::Expr) -> Option<ast::Expr> {
+    match expr {
+        ast::Expr::BinExpr(bin) => {
+            let op_kind = bin.op_kind()?;
+            let rev_kind = match op_kind {
+                ast::BinaryOp::CmpOp(ast::CmpOp::Eq { negated }) => {
+                    ast::BinaryOp::CmpOp(ast::CmpOp::Eq { negated: !negated })
+                }
+                ast::BinaryOp::CmpOp(ast::CmpOp::Ord { ordering: ast::Ordering::Less, strict }) => {
+                    ast::BinaryOp::CmpOp(ast::CmpOp::Ord {
+                        ordering: ast::Ordering::Greater,
+                        strict: !strict,
+                    })
+                }
+                ast::BinaryOp::CmpOp(ast::CmpOp::Ord {
+                    ordering: ast::Ordering::Greater,
+                    strict,
+                }) => ast::BinaryOp::CmpOp(ast::CmpOp::Ord {
+                    ordering: ast::Ordering::Less,
+                    strict: !strict,
+                }),
+                // Parenthesize other expressions before prefixing `!`
+                _ => {
+                    return Some(
+                        make.expr_prefix(T![!], make.expr_paren(expr.clone()).into()).into(),
+                    );
+                }
+            };
+
+            Some(make.expr_bin(bin.lhs()?, rev_kind, bin.rhs()?).into())
+        }
+        ast::Expr::MethodCallExpr(mce) => {
+            let receiver = mce.receiver()?;
+            let method = mce.name_ref()?;
+            let arg_list = mce.arg_list()?;
+
+            let method = match method.text().as_str() {
+                "is_some" => "is_none",
+                "is_none" => "is_some",
+                "is_ok" => "is_err",
+                "is_err" => "is_ok",
+                _ => return None,
+            };
+
+            Some(make.expr_method_call(receiver, make.name_ref(method), arg_list).into())
+        }
+        ast::Expr::PrefixExpr(pe) if pe.op_kind()? == ast::UnaryOp::Not => match pe.expr()? {
+            ast::Expr::ParenExpr(parexpr) => {
+                parexpr.expr().map(|e| e.clone_subtree().clone_for_update())
+            }
+            _ => pe.expr().map(|e| e.clone_subtree().clone_for_update()),
+        },
+        ast::Expr::Literal(lit) => match lit.kind() {
+            ast::LiteralKind::Bool(b) => match b {
+                true => Some(ast::Expr::Literal(make.expr_literal("false"))),
+                false => Some(ast::Expr::Literal(make.expr_literal("true"))),
+            },
+            _ => None,
+        },
+        _ => None,
+    }
+}
+
+fn invert_special_case_legacy(expr: &ast::Expr) -> Option<ast::Expr> {
     match expr {
         ast::Expr::BinExpr(bin) => {
             let bin = bin.clone_for_update();
diff --git a/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml b/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml
index 1bef82af5ac..68cc7a0b9a6 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 cov-mark = "2.0.0-pre.1"
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 e7101751701..365d2dde7e9 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
@@ -147,7 +147,10 @@ pub(crate) fn complete_expr_path(
             });
             match resolution {
                 hir::PathResolution::Def(hir::ModuleDef::Module(module)) => {
-                    let module_scope = module.scope(ctx.db, Some(ctx.module));
+                    // Set visible_from to None so private items are returned.
+                    // They will be possibly filtered out in add_path_resolution()
+                    // via def_is_visible().
+                    let module_scope = module.scope(ctx.db, None);
                     for (name, def) in module_scope {
                         if scope_def_applicable(def) {
                             acc.add_path_resolution(
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 7862b258789..919b30f7f97 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
@@ -249,8 +249,8 @@ pub(crate) enum Qualified {
         /// This would be None, if path is not solely made of
         /// `super` segments, e.g.
         ///
-        /// ```rust
-        ///   use super::foo;
+        /// ```ignore
+        /// use super::foo;
         /// ```
         ///
         /// Otherwise it should be Some(count of `super`)
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 eecd412bc43..1a34548f708 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
@@ -97,7 +97,8 @@ fn token_at_offset_ignore_whitespace(file: &SyntaxNode, offset: TextSize) -> Opt
 /// We do this by recursively expanding all macros and picking the best possible match. We cannot just
 /// choose the first expansion each time because macros can expand to something that does not include
 /// our completion marker, e.g.:
-/// ```
+///
+/// ```ignore
 /// macro_rules! helper { ($v:ident) => {} }
 /// macro_rules! my_macro {
 ///     ($v:ident) => {
@@ -106,7 +107,7 @@ fn token_at_offset_ignore_whitespace(file: &SyntaxNode, offset: TextSize) -> Opt
 ///     };
 /// }
 ///
-/// my_macro!(complete_me_here)
+/// my_macro!(complete_me_here);
 /// ```
 /// If we would expand the first thing we encounter only (which in fact this method used to do), we would
 /// be unable to complete here, because we would be walking directly into the void. So we instead try
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 41a82409597..b3dd8a8d06e 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/item.rs
@@ -149,9 +149,9 @@ pub struct CompletionRelevance {
     /// This is set when the identifier being completed matches up with the name that is expected,
     /// like in a function argument.
     ///
-    /// ```
+    /// ```ignore
     /// fn f(spam: String) {}
-    /// fn main {
+    /// fn main() {
     ///     let spam = 92;
     ///     f($0) // name of local matches the name of param
     /// }
@@ -161,7 +161,7 @@ pub struct CompletionRelevance {
     pub type_match: Option<CompletionRelevanceTypeMatch>,
     /// Set for local variables.
     ///
-    /// ```
+    /// ```ignore
     /// fn foo(a: u32) {
     ///     let b = 0;
     ///     $0 // `a` and `b` are local
@@ -195,7 +195,7 @@ pub struct CompletionRelevanceTraitInfo {
 pub enum CompletionRelevanceTypeMatch {
     /// This is set in cases like these:
     ///
-    /// ```
+    /// ```ignore
     /// enum Option<T> { Some(T), None }
     /// fn f(a: Option<u32>) {}
     /// fn main {
@@ -205,9 +205,9 @@ pub enum CompletionRelevanceTypeMatch {
     CouldUnify,
     /// This is set in cases where the type matches the expected type, like:
     ///
-    /// ```
+    /// ```ignore
     /// fn f(spam: String) {}
-    /// fn main {
+    /// fn main() {
     ///     let foo = String::new();
     ///     f($0) // type of local matches the type of param
     /// }
@@ -221,7 +221,7 @@ pub enum CompletionRelevancePostfixMatch {
     NonExact,
     /// This is set in cases like these:
     ///
-    /// ```
+    /// ```ignore
     /// (a > b).not$0
     /// ```
     ///
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 a1f2eaeb1b6..a990b39481a 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/lib.rs
@@ -143,7 +143,7 @@ impl CompletionFieldsToResolve {
 /// already present, it should give all possible variants for the identifier at
 /// the caret. In other words, for
 ///
-/// ```no_run
+/// ```ignore
 /// fn f() {
 ///     let foo = 92;
 ///     let _ = bar$0
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 dc7eacbfbaf..4f6c4cb6639 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/render.rs
@@ -628,11 +628,9 @@ fn compute_ref_match(
     let expected_type = ctx.expected_type.as_ref()?;
     let expected_without_ref = expected_type.remove_ref();
     let completion_without_ref = completion_ty.remove_ref();
-
-    if completion_ty == expected_type {
+    if expected_type.could_unify_with(ctx.db, completion_ty) {
         return None;
     }
-
     if let Some(expected_without_ref) = &expected_without_ref {
         if completion_ty.autoderef(ctx.db).any(|ty| ty == *expected_without_ref) {
             cov_mark::hit!(suggest_ref);
@@ -2008,6 +2006,30 @@ fn f() {
     }
 
     #[test]
+    fn test_avoid_redundant_suggestion() {
+        check_relevance(
+            r#"
+struct aa([u8]);
+
+impl aa {
+    fn from_bytes(bytes: &[u8]) -> &Self {
+        unsafe { &*(bytes as *const [u8] as *const aa) }
+    }
+}
+
+fn bb()-> &'static aa {
+    let bytes = b"hello";
+    aa::$0
+}
+"#,
+            expect![[r#"
+                ex bb()  [type]
+                fn from_bytes(…) fn(&[u8]) -> &aa [type_could_unify]
+            "#]],
+        );
+    }
+
+    #[test]
     fn suggest_ref_mut() {
         cov_mark::check!(suggest_ref);
         check_relevance(
diff --git a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml
index c8a8a2d1698..641998c3dac 100644
--- a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 cov-mark = "2.0.0-pre.1"
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs
index ed9d6c67501..9c983e7c4a6 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs
@@ -12317,40 +12317,6 @@ will unnecessarily extend the stack frame.
         deny_since: None,
     },
     Lint {
-        label: "unsized_tuple_coercion",
-        description: r##"# `unsized_tuple_coercion`
-
-The tracking issue for this feature is: [#42877]
-
-[#42877]: https://github.com/rust-lang/rust/issues/42877
-
-------------------------
-
-This is a part of [RFC0401]. According to the RFC, there should be an implementation like this:
-
-```rust,ignore (partial-example)
-impl<..., T, U: ?Sized> Unsized<(..., U)> for (..., T) where T: Unsized<U> {}
-```
-
-This implementation is currently gated behind `#[feature(unsized_tuple_coercion)]` to avoid insta-stability. Therefore you can use it like this:
-
-```rust
-#![feature(unsized_tuple_coercion)]
-
-fn main() {
-    let x : ([i32; 3], [i32; 3]) = ([1, 2, 3], [4, 5, 6]);
-    let y : &([i32; 3], [i32]) = &x;
-    assert_eq!(y.1[0], 4);
-}
-```
-
-[RFC0401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
-"##,
-        default_severity: Severity::Allow,
-        warn_since: None,
-        deny_since: None,
-    },
-    Lint {
         label: "unwrap_infallible",
         description: r##"# `unwrap_infallible`
 
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 3a29232d331..96115eee6dc 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
@@ -252,10 +252,10 @@ pub enum SymbolKind {
 impl From<hir::MacroKind> for SymbolKind {
     fn from(it: hir::MacroKind) -> Self {
         match it {
-            hir::MacroKind::Declarative | hir::MacroKind::BuiltIn => SymbolKind::Macro,
+            hir::MacroKind::Declarative | hir::MacroKind::DeclarativeBuiltIn => SymbolKind::Macro,
             hir::MacroKind::ProcMacro => SymbolKind::ProcMacro,
-            hir::MacroKind::Derive => SymbolKind::Derive,
-            hir::MacroKind::Attr => SymbolKind::Attribute,
+            hir::MacroKind::Derive | hir::MacroKind::DeriveBuiltIn => SymbolKind::Derive,
+            hir::MacroKind::Attr | hir::MacroKind::AttrBuiltIn => SymbolKind::Attribute,
         }
     }
 }
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 f045e44dd31..126b30470b7 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
@@ -32,7 +32,7 @@ type DefaultedParam = Either<hir::TypeParam, hir::ConstParam>;
 /// block), you generally want to appropriately qualify the names, and sometimes
 /// you might want to substitute generic parameters as well:
 ///
-/// ```
+/// ```ignore
 /// mod x {
 ///   pub struct A<V>;
 ///   pub trait T<U> { fn foo(&self, _: U) -> A<U>; }
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 7963e8ae4f7..02cd8b8bdf5 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/search.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/search.rs
@@ -373,7 +373,9 @@ impl Definition {
                         SearchScope::krate(db, module.krate())
                     }
                 }
-                hir::MacroKind::BuiltIn => SearchScope::crate_graph(db),
+                hir::MacroKind::AttrBuiltIn
+                | hir::MacroKind::DeriveBuiltIn
+                | hir::MacroKind::DeclarativeBuiltIn => SearchScope::crate_graph(db),
                 hir::MacroKind::Derive | hir::MacroKind::Attr | hir::MacroKind::ProcMacro => {
                     SearchScope::reverse_dependencies(db, module.krate())
                 }
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs b/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs
index 27ff91dc19d..34642d7eaf9 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/source_change.rs
@@ -493,7 +493,7 @@ pub enum Snippet {
     Placeholder(TextRange),
     /// A group of placeholder snippets, e.g.
     ///
-    /// ```no_run
+    /// ```ignore
     /// let ${0:new_var} = 4;
     /// fun(1, 2, 3, ${0:new_var});
     /// ```
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 0a7141c19b6..e085bf15cb9 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
@@ -79,7 +79,9 @@ const USELESS_METHODS: &[&str] = &[
 /// the name, e.g. `a`, `a1`, `a2`, ...
 ///
 /// # Examples
-/// ```rust
+///
+/// ```
+/// # use ide_db::syntax_helpers::suggest_name::NameGenerator;
 /// let mut generator = NameGenerator::new();
 /// assert_eq!(generator.suggest_name("a"), "a");
 /// assert_eq!(generator.suggest_name("a"), "a1");
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml b/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml
index 281a08e5429..483cb6df862 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 cov-mark = "2.0.0-pre.1"
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 323a5723d4a..040aa2949aa 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
@@ -854,7 +854,7 @@ fn main() {
 #[target_feature(enable = "avx")]
 fn foo() {}
 
-#[target_feature(enable = "avx,avx2")]
+#[target_feature(enable = "avx2")]
 fn bar() {
     foo();
 }
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
index 3ea41aa7e85..0a55b6e9bee 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
@@ -697,7 +697,7 @@ struct SeverityAttr {
     /// #[warn(non_snake_case)]
     /// mod foo {
     ///     #[allow(nonstandard_style)]
-    ///     mod bar;
+    ///     mod bar {}
     /// }
     /// ```
     /// We want to not warn on non snake case inside `bar`. If we are traversing this for the first
diff --git a/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml b/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml
index 25614676288..fa75e5a4214 100644
--- a/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-ssr/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 cov-mark = "2.0.0-pre.1"
diff --git a/src/tools/rust-analyzer/crates/ide/Cargo.toml b/src/tools/rust-analyzer/crates/ide/Cargo.toml
index 7c66b36dc8e..9af56c40e98 100644
--- a/src/tools/rust-analyzer/crates/ide/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 cov-mark = "2.0.0-pre.1"
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 e35e47e7471..8d2ca33bf25 100644
--- a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
@@ -379,13 +379,15 @@ fn rewrite_intra_doc_link(
     let resolved = resolve_doc_path_for_def(db, def, link, ns)?;
     let mut url = get_doc_base_urls(db, resolved, None, None).0?;
 
-    let (_, file, _) = filename_and_frag_for_def(db, resolved)?;
+    let (_, file, frag) = filename_and_frag_for_def(db, resolved)?;
     if let Some(path) = mod_path_of_def(db, resolved) {
         url = url.join(&path).ok()?;
     }
 
+    let frag = anchor.or(frag.as_deref());
+
     url = url.join(&file).ok()?;
-    url.set_fragment(anchor);
+    url.set_fragment(frag);
 
     Some((url.into(), strip_prefixes_suffixes(title).to_owned()))
 }
@@ -621,11 +623,9 @@ fn filename_and_frag_for_def(
             format!("fn.{}.html", f.name(db).as_str())
         }
         Definition::Variant(ev) => {
-            format!(
-                "enum.{}.html#variant.{}",
-                ev.parent_enum(db).name(db).as_str(),
-                ev.name(db).as_str()
-            )
+            let def = Definition::Adt(ev.parent_enum(db).into());
+            let (_, file, _) = filename_and_frag_for_def(db, def)?;
+            return Some((def, file, Some(format!("variant.{}", ev.name(db).as_str()))));
         }
         Definition::Const(c) => {
             format!("const.{}.html", c.name(db)?.as_str())
@@ -635,12 +635,13 @@ fn filename_and_frag_for_def(
         }
         Definition::Macro(mac) => match mac.kind(db) {
             hir::MacroKind::Declarative
-            | hir::MacroKind::BuiltIn
+            | hir::MacroKind::AttrBuiltIn
+            | hir::MacroKind::DeclarativeBuiltIn
             | hir::MacroKind::Attr
             | hir::MacroKind::ProcMacro => {
                 format!("macro.{}.html", mac.name(db).as_str())
             }
-            hir::MacroKind::Derive => {
+            hir::MacroKind::Derive | hir::MacroKind::DeriveBuiltIn => {
                 format!("derive.{}.html", mac.name(db).as_str())
             }
         },
diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs
index d7291c4b9f3..b09e3a3c804 100644
--- a/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs
@@ -686,3 +686,95 @@ fn rewrite_intra_doc_link_with_anchor() {
         expect!["[PartialEq#derivable](https://doc.rust-lang.org/stable/core/cmp/trait.PartialEq.html#derivable)"],
     );
 }
+
+#[test]
+fn rewrite_intra_doc_link_to_associated_item() {
+    check_rewrite(
+        r#"
+//- /main.rs crate:foo
+/// [Foo::bar]
+pub struct $0Foo;
+
+impl Foo {
+    fn bar() {}
+}
+"#,
+        expect![[r#"[Foo::bar](https://docs.rs/foo/*/foo/struct.Foo.html#method.bar)"#]],
+    );
+    check_rewrite(
+        r#"
+//- /main.rs crate:foo
+/// [Foo::bar]
+pub struct $0Foo {
+    bar: ()
+}
+"#,
+        expect![[r#"[Foo::bar](https://docs.rs/foo/*/foo/struct.Foo.html#structfield.bar)"#]],
+    );
+    check_rewrite(
+        r#"
+//- /main.rs crate:foo
+/// [Foo::Bar]
+pub enum $0Foo {
+    Bar
+}
+"#,
+        expect![[r#"[Foo::Bar](https://docs.rs/foo/*/foo/enum.Foo.html#variant.Bar)"#]],
+    );
+    check_rewrite(
+        r#"
+//- /main.rs crate:foo
+/// [Foo::BAR]
+pub struct $0Foo;
+
+impl Foo {
+    const BAR: () = ();
+}
+"#,
+        expect![[
+            r#"[Foo::BAR](https://docs.rs/foo/*/foo/struct.Foo.html#associatedconstant.BAR)"#
+        ]],
+    );
+    check_rewrite(
+        r#"
+//- /main.rs crate:foo
+/// [Foo::bar]
+pub trait $0Foo {
+    fn bar();
+}
+"#,
+        expect![[r#"[Foo::bar](https://docs.rs/foo/*/foo/trait.Foo.html#tymethod.bar)"#]],
+    );
+    check_rewrite(
+        r#"
+//- /main.rs crate:foo
+/// [Foo::Bar]
+pub trait $0Foo {
+    type Bar;
+}
+"#,
+        expect![[r#"[Foo::Bar](https://docs.rs/foo/*/foo/trait.Foo.html#associatedtype.Bar)"#]],
+    );
+    check_rewrite(
+        r#"
+//- /main.rs crate:foo
+/// [Foo::bar#anchor]
+pub struct $0Foo {
+    bar: (),
+}
+"#,
+        expect![[r#"[Foo::bar#anchor](https://docs.rs/foo/*/foo/struct.Foo.html#anchor)"#]],
+    );
+    check_rewrite(
+        r#"
+//- /main.rs crate:foo
+/// [method](Foo::bar)
+pub struct $0Foo;
+
+impl Foo {
+    fn bar() {}
+}
+"#,
+        expect![[r#"[method](https://docs.rs/foo/*/foo/struct.Foo.html#method.bar)"#]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs
index 95a720e7e45..9a3e77f3a93 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs
@@ -38,6 +38,7 @@ pub struct HoverConfig {
     pub max_fields_count: Option<usize>,
     pub max_enum_variants_count: Option<usize>,
     pub max_subst_ty_len: SubstTyLen,
+    pub show_drop_glue: bool,
 }
 
 #[derive(Clone, Debug, PartialEq, Eq)]
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
index c996230c3a1..c5a83e58cea 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
@@ -3,7 +3,7 @@ use std::{env, mem, ops::Not};
 
 use either::Either;
 use hir::{
-    db::ExpandDatabase, Adt, AsAssocItem, AsExternAssocItem, CaptureKind,
+    db::ExpandDatabase, Adt, AsAssocItem, AsExternAssocItem, CaptureKind, DropGlue,
     DynCompatibilityViolation, HasCrate, HasSource, HirDisplay, Layout, LayoutError,
     MethodViolationCode, Name, Semantics, Symbol, Trait, Type, TypeInfo, VariantDef,
 };
@@ -629,6 +629,89 @@ pub(super) fn definition(
         _ => None,
     };
 
+    let drop_info = || {
+        if !config.show_drop_glue {
+            return None;
+        }
+        let drop_info = match def {
+            Definition::Field(field) => {
+                DropInfo { drop_glue: field.ty(db).drop_glue(db), has_dtor: None }
+            }
+            Definition::Adt(Adt::Struct(strukt)) => {
+                let struct_drop_glue = strukt.ty_placeholders(db).drop_glue(db);
+                let mut fields_drop_glue = strukt
+                    .fields(db)
+                    .iter()
+                    .map(|field| field.ty(db).drop_glue(db))
+                    .max()
+                    .unwrap_or(DropGlue::None);
+                let has_dtor = match (fields_drop_glue, struct_drop_glue) {
+                    (DropGlue::None, _) => struct_drop_glue != DropGlue::None,
+                    (_, DropGlue::None) => {
+                        // This is `ManuallyDrop`.
+                        fields_drop_glue = DropGlue::None;
+                        false
+                    }
+                    (_, _) => struct_drop_glue > fields_drop_glue,
+                };
+                DropInfo { drop_glue: fields_drop_glue, has_dtor: Some(has_dtor) }
+            }
+            // Unions cannot have fields with drop glue.
+            Definition::Adt(Adt::Union(union)) => DropInfo {
+                drop_glue: DropGlue::None,
+                has_dtor: Some(union.ty_placeholders(db).drop_glue(db) != DropGlue::None),
+            },
+            Definition::Adt(Adt::Enum(enum_)) => {
+                let enum_drop_glue = enum_.ty_placeholders(db).drop_glue(db);
+                let fields_drop_glue = enum_
+                    .variants(db)
+                    .iter()
+                    .map(|variant| {
+                        variant
+                            .fields(db)
+                            .iter()
+                            .map(|field| field.ty(db).drop_glue(db))
+                            .max()
+                            .unwrap_or(DropGlue::None)
+                    })
+                    .max()
+                    .unwrap_or(DropGlue::None);
+                DropInfo {
+                    drop_glue: fields_drop_glue,
+                    has_dtor: Some(enum_drop_glue > fields_drop_glue),
+                }
+            }
+            Definition::Variant(variant) => {
+                let fields_drop_glue = variant
+                    .fields(db)
+                    .iter()
+                    .map(|field| field.ty(db).drop_glue(db))
+                    .max()
+                    .unwrap_or(DropGlue::None);
+                DropInfo { drop_glue: fields_drop_glue, has_dtor: None }
+            }
+            Definition::TypeAlias(type_alias) => {
+                DropInfo { drop_glue: type_alias.ty_placeholders(db).drop_glue(db), has_dtor: None }
+            }
+            Definition::Local(local) => {
+                DropInfo { drop_glue: local.ty(db).drop_glue(db), has_dtor: None }
+            }
+            _ => return None,
+        };
+        let rendered_drop_glue = match drop_info.drop_glue {
+            DropGlue::None => "does not contain types with destructors (drop glue)",
+            DropGlue::DependOnParams => {
+                "may contain types with destructors (drop glue) depending on type parameters"
+            }
+            DropGlue::HasDropGlue => "contain types with destructors (drop glue)",
+        };
+        Some(match drop_info.has_dtor {
+            Some(true) => format!("{}; has a destructor", rendered_drop_glue),
+            Some(false) => format!("{}; doesn't have a destructor", rendered_drop_glue),
+            None => rendered_drop_glue.to_owned(),
+        })
+    };
+
     let dyn_compatibility_info = || match def {
         Definition::Trait(it) => {
             let mut dyn_compatibility_info = String::new();
@@ -661,6 +744,10 @@ pub(super) fn definition(
             extra.push_str("\n___\n");
             extra.push_str(&dyn_compatibility_info);
         }
+        if let Some(drop_info) = drop_info() {
+            extra.push_str("\n___\n");
+            extra.push_str(&drop_info);
+        }
     }
     let mut desc = String::new();
     desc.push_str(&label);
@@ -703,6 +790,12 @@ pub(super) fn definition(
     )
 }
 
+#[derive(Debug)]
+struct DropInfo {
+    drop_glue: DropGlue,
+    has_dtor: Option<bool>,
+}
+
 pub(super) fn literal(
     sema: &Semantics<'_, RootDatabase>,
     token: SyntaxToken,
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 8c32cc9720a..7c720d97cb6 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
@@ -21,6 +21,7 @@ const HOVER_BASE_CONFIG: HoverConfig = HoverConfig {
     max_fields_count: Some(5),
     max_enum_variants_count: Some(5),
     max_subst_ty_len: super::SubstTyLen::Unlimited,
+    show_drop_glue: true,
 };
 
 fn check_hover_no_result(#[rust_analyzer::rust_fixture] ra_fixture: &str) {
@@ -567,6 +568,10 @@ fn main() {
             ---
 
             size = 8, align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -812,6 +817,10 @@ struct Foo { fiel$0d_a: u8, field_b: i32, field_c: i16 }
             ---
 
             size = 1, align = 1, offset = 6
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -863,6 +872,10 @@ fn main() {
             ---
 
             size = 4, align = 4, offset = 0
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -933,6 +946,10 @@ struct Foo$0(pub u32) where u32: Copy;
             ---
 
             size = 4, align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
         "#]],
     );
 }
@@ -959,6 +976,10 @@ struct Foo$0 { field: u32 }
             ---
 
             size = 4, align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
         "#]],
     );
     check(
@@ -984,6 +1005,10 @@ struct Foo$0 where u32: Copy { field: u32 }
             ---
 
             size = 4, align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
         "#]],
     );
 }
@@ -1013,6 +1038,10 @@ fn hover_record_struct_limit() {
             ---
 
             size = 12 (0xC), align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
         "#]],
     );
     check_hover_fields_limit(
@@ -1036,6 +1065,10 @@ fn hover_record_struct_limit() {
             ---
 
             size = 4, align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
         "#]],
     );
     check_hover_fields_limit(
@@ -1062,6 +1095,10 @@ fn hover_record_struct_limit() {
             ---
 
             size = 16 (0x10), align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
         "#]],
     );
     check_hover_fields_limit(
@@ -1083,6 +1120,10 @@ fn hover_record_struct_limit() {
             ---
 
             size = 12 (0xC), align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
         "#]],
     );
     check_hover_fields_limit(
@@ -1104,6 +1145,10 @@ fn hover_record_struct_limit() {
             ---
 
             size = 12 (0xC), align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
         "#]],
     );
 
@@ -1127,6 +1172,10 @@ fn hover_record_struct_limit() {
             ---
 
             size = 0, align = 1
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
         "#]],
     );
 }
@@ -1152,6 +1201,10 @@ fn hover_record_variant_limit() {
             ---
 
             size = 12 (0xC), align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
     check_hover_fields_limit(
@@ -1173,6 +1226,10 @@ fn hover_record_variant_limit() {
             ---
 
             size = 4, align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
     check_hover_fields_limit(
@@ -1194,6 +1251,10 @@ fn hover_record_variant_limit() {
             ---
 
             size = 16 (0x10), align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
     check_hover_fields_limit(
@@ -1215,6 +1276,10 @@ fn hover_record_variant_limit() {
             ---
 
             size = 12 (0xC), align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
     check_hover_fields_limit(
@@ -1236,6 +1301,10 @@ fn hover_record_variant_limit() {
             ---
 
             size = 12 (0xC), align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -1262,6 +1331,10 @@ fn hover_enum_limit() {
             ---
 
             size = 1, align = 1, niches = 254
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
         "#]],
     );
     check_hover_enum_variants_limit(
@@ -1284,6 +1357,10 @@ fn hover_enum_limit() {
             ---
 
             size = 1, align = 1, niches = 254
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
         "#]],
     );
     check_hover_enum_variants_limit(
@@ -1303,6 +1380,10 @@ fn hover_enum_limit() {
             ---
 
             size = 1, align = 1, niches = 254
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
         "#]],
     );
     check_hover_enum_variants_limit(
@@ -1322,6 +1403,10 @@ fn hover_enum_limit() {
             ---
 
             size = 1, align = 1, niches = 254
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
         "#]],
     );
     check_hover_enum_variants_limit(
@@ -1359,6 +1444,10 @@ fn hover_enum_limit() {
             ---
 
             size = 12 (0xC), align = 4, niches = a lot
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
         "#]],
     );
 }
@@ -1385,6 +1474,10 @@ fn hover_union_limit() {
             ---
 
             size = 4, align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
         "#]],
     );
     check_hover_fields_limit(
@@ -1407,6 +1500,10 @@ fn hover_union_limit() {
             ---
 
             size = 4, align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
         "#]],
     );
     check_hover_fields_limit(
@@ -1426,6 +1523,10 @@ fn hover_union_limit() {
             ---
 
             size = 4, align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
         "#]],
     );
     check_hover_fields_limit(
@@ -1445,6 +1546,10 @@ fn hover_union_limit() {
             ---
 
             size = 4, align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
         "#]],
     );
 }
@@ -1471,6 +1576,10 @@ struct Foo$0 where u32: Copy;
             ---
 
             size = 0, align = 1
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
         "#]],
     );
 }
@@ -1493,6 +1602,10 @@ type Fo$0o: Trait = S where T: Trait;
             where
                 T: Trait,
             ```
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -1642,6 +1755,10 @@ fn main() {
             ---
 
             size = 8, align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
     check_hover_range(
@@ -1697,6 +1814,10 @@ fn main() { let b$0ar = Some(12); }
             ---
 
             size = 4, align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -1724,6 +1845,10 @@ enum Option<T> {
 
             ---
 
+            does not contain types with destructors (drop glue)
+
+            ---
+
             The None variant
         "#]],
     );
@@ -1784,6 +1909,10 @@ fn hover_for_local_variable_pat() {
             ---
 
             size = 4, align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     )
 }
@@ -1816,6 +1945,10 @@ fn hover_for_param_edge() {
             ---
 
             size = 4, align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     )
 }
@@ -1838,6 +1971,10 @@ fn hover_for_param_with_multiple_traits() {
             ```rust
             _x: impl Deref<Target = u8> + DerefMut<Target = u8>
             ```
+
+            ---
+
+            may contain types with destructors (drop glue) depending on type parameters
         "#]],
     )
 }
@@ -1864,6 +2001,10 @@ fn main() { let foo_$0test = Thing::new(); }
             ---
 
             size = 4, align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     )
 }
@@ -2613,6 +2754,10 @@ fn test_hover_function_pointer_show_identifiers() {
             ---
 
             size = 8, align = 8, niches = 1
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -2635,6 +2780,10 @@ fn test_hover_function_pointer_no_identifier() {
             ---
 
             size = 8, align = 8, niches = 1
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -2881,6 +3030,10 @@ pub struct B$0ar
 
             ---
 
+            does not contain types with destructors (drop glue); doesn't have a destructor
+
+            ---
+
             [external](https://www.google.com)
         "#]],
     );
@@ -2912,6 +3065,10 @@ pub struct B$0ar
 
             ---
 
+            does not contain types with destructors (drop glue); doesn't have a destructor
+
+            ---
+
             [baz](Baz)
         "#]],
     );
@@ -3002,6 +3159,10 @@ fn test_hover_layout_of_variant() {
             ---
 
             size = 4, align = 2
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -3023,6 +3184,10 @@ fn test_hover_layout_of_variant_generic() {
             ```rust
             None
             ```
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -3048,6 +3213,10 @@ struct S$0<T>(core::marker::PhantomData<T>);
             ---
 
             size = 0, align = 1
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
         "#]],
     );
 }
@@ -3076,6 +3245,10 @@ fn test_hover_layout_of_enum() {
             ---
 
             size = 16 (0x10), align = 8, niches = 254
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
         "#]],
     );
 }
@@ -3094,6 +3267,10 @@ fn test_hover_no_memory_layout() {
             ```rust
             field_a: u8
             ```
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 
@@ -4405,6 +4582,10 @@ fn main() {
 
             ---
 
+            does not contain types with destructors (drop glue)
+
+            ---
+
             ```rust
             ra_test_fixture::S
             ```
@@ -4416,6 +4597,10 @@ fn main() {
             ---
 
             size = 4, align = 4, offset = 0
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -4441,6 +4626,10 @@ struct S$0T<const C: usize = 1, T = Foo>(T);
             ---
 
             size = 0, align = 1
+
+            ---
+
+            may contain types with destructors (drop glue) depending on type parameters; doesn't have a destructor
         "#]],
     );
 }
@@ -4466,6 +4655,10 @@ struct S$0T<const C: usize = {40 + 2}, T = Foo>(T);
             ---
 
             size = 0, align = 1
+
+            ---
+
+            may contain types with destructors (drop glue) depending on type parameters; doesn't have a destructor
         "#]],
     );
 }
@@ -4492,6 +4685,10 @@ struct S$0T<const C: usize = VAL, T = Foo>(T);
             ---
 
             size = 0, align = 1
+
+            ---
+
+            may contain types with destructors (drop glue) depending on type parameters; doesn't have a destructor
         "#]],
     );
 }
@@ -4516,6 +4713,10 @@ fn main() {
             ---
 
             size = 0, align = 1
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -4540,6 +4741,10 @@ fn main() {
             ---
 
             size = 0, align = 1
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -4564,6 +4769,10 @@ fn main() {
             ---
 
             size = 0, align = 1
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -4588,6 +4797,10 @@ fn main() {
             ---
 
             size = 0, align = 1
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -4612,6 +4825,10 @@ fn main() {
             ---
 
             size = 0, align = 1
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -4635,6 +4852,10 @@ impl Foo {
             ---
 
             size = 8, align = 8, niches = 1
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -4659,6 +4880,10 @@ impl Foo {
             ---
 
             size = 0, align = 1
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -5149,6 +5374,10 @@ type Fo$0o2 = Foo<2>;
             ---
 
             size = 0, align = 1
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -5202,6 +5431,10 @@ enum E {
 
             ---
 
+            does not contain types with destructors (drop glue)
+
+            ---
+
             This is a doc
         "#]],
     );
@@ -5231,6 +5464,10 @@ enum E {
 
             ---
 
+            does not contain types with destructors (drop glue)
+
+            ---
+
             This is a doc
         "#]],
     );
@@ -5261,6 +5498,10 @@ enum E {
 
             ---
 
+            does not contain types with destructors (drop glue)
+
+            ---
+
             This is a doc
         "#]],
     );
@@ -5291,6 +5532,10 @@ enum E {
 
             ---
 
+            does not contain types with destructors (drop glue)
+
+            ---
+
             This is a doc
         "#]],
     );
@@ -6219,6 +6464,10 @@ fn main() {
             ---
 
             size = 32 (0x20), align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -7518,6 +7767,10 @@ enum Enum {
             ---
 
             size = 4, align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -7544,6 +7797,10 @@ enum Enum {
             ---
 
             size = 4, align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -8214,6 +8471,10 @@ fn test() {
             ---
 
             size = 0, align = 1
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -8863,6 +9124,10 @@ fn main(notable$0: u32) {}
             ---
 
             size = 4, align = 4
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -8955,6 +9220,10 @@ extern "C" {
             ---
 
             size = 0, align = 1
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -9101,6 +9370,10 @@ struct Pedro$0<'a> {
             ---
 
             size = 16 (0x10), align = 8, niches = 1
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
         "#]],
     )
 }
@@ -9118,6 +9391,10 @@ fn main(a$0: impl T) {}
             ```rust
             a: impl T + ?Sized
             ```
+
+            ---
+
+            may contain types with destructors (drop glue) depending on type parameters
         "#]],
     );
 }
@@ -9139,6 +9416,10 @@ fn main(a$0: T) {}
             ---
 
             size = 0, align = 1
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -9192,6 +9473,10 @@ fn main() {
             ---
 
             size = 0, align = 1
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -9529,6 +9814,10 @@ type A$0 = B;
 
             ---
 
+            does not contain types with destructors (drop glue)
+
+            ---
+
             *This is the documentation for* `struct B`
 
             Docs for B
@@ -9562,6 +9851,10 @@ type A$0 = B;
 
             ---
 
+            does not contain types with destructors (drop glue)
+
+            ---
+
             *This is the documentation for* `struct C`
 
             Docs for C
@@ -9596,6 +9889,10 @@ type A$0 = B;
 
             ---
 
+            does not contain types with destructors (drop glue)
+
+            ---
+
             *This is the documentation for* `struct C`
 
             Docs for C
@@ -9625,6 +9922,10 @@ type A$0 = B;
             ---
 
             size = 0, align = 1
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 
@@ -9749,6 +10050,10 @@ fn main() {
             ---
 
             size = 0, align = 1
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 
@@ -9777,6 +10082,10 @@ fn main() {
             ---
 
             size = 0, align = 1
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 
@@ -9812,6 +10121,10 @@ fn main() {
             ---
 
             size = 0, align = 1
+
+            ---
+
+            does not contain types with destructors (drop glue)
         "#]],
     );
 }
@@ -10134,6 +10447,10 @@ fn bar() {
 
             ---
 
+            does not contain types with destructors (drop glue)
+
+            ---
+
             ```rust
             ra_test_fixture::Foo
             ```
@@ -10144,6 +10461,10 @@ fn bar() {
 
             ---
 
+            may contain types with destructors (drop glue) depending on type parameters
+
+            ---
+
             `T` = `i32`
         "#]],
     );
@@ -10353,3 +10674,276 @@ macro_rules! str {
         "#]],
     );
 }
+
+#[test]
+fn drop_glue() {
+    check(
+        r#"
+struct NoDrop$0;
+    "#,
+        expect![[r#"
+            *NoDrop*
+
+            ```rust
+            ra_test_fixture
+            ```
+
+            ```rust
+            struct NoDrop
+            ```
+
+            ---
+
+            size = 0, align = 1
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
+        "#]],
+    );
+    check(
+        r#"
+//- minicore: drop
+struct NeedsDrop$0;
+impl Drop for NeedsDrop {
+    fn drop(&mut self) {}
+}
+    "#,
+        expect![[r#"
+            *NeedsDrop*
+
+            ```rust
+            ra_test_fixture
+            ```
+
+            ```rust
+            struct NeedsDrop
+            ```
+
+            ---
+
+            size = 0, align = 1
+
+            ---
+
+            does not contain types with destructors (drop glue); has a destructor
+        "#]],
+    );
+    check(
+        r#"
+//- minicore: manually_drop, drop
+struct NeedsDrop;
+impl Drop for NeedsDrop {
+    fn drop(&mut self) {}
+}
+type NoDrop$0 = core::mem::ManuallyDrop<NeedsDrop>;
+    "#,
+        expect![[r#"
+            *NoDrop*
+
+            ```rust
+            ra_test_fixture
+            ```
+
+            ```rust
+            type NoDrop = core::mem::ManuallyDrop<NeedsDrop>
+            ```
+
+            ---
+
+            size = 0, align = 1
+
+            ---
+
+            does not contain types with destructors (drop glue)
+        "#]],
+    );
+    check(
+        r#"
+//- minicore: drop
+struct NeedsDrop;
+impl Drop for NeedsDrop {
+    fn drop(&mut self) {}
+}
+struct DropField$0 {
+    _x: i32,
+    _y: NeedsDrop,
+}
+    "#,
+        expect![[r#"
+            *DropField*
+
+            ```rust
+            ra_test_fixture
+            ```
+
+            ```rust
+            struct DropField {
+                _x: i32,
+                _y: NeedsDrop,
+            }
+            ```
+
+            ---
+
+            size = 4, align = 4
+
+            ---
+
+            contain types with destructors (drop glue); doesn't have a destructor
+        "#]],
+    );
+    check(
+        r#"
+//- minicore: sized
+type Foo$0 = impl Sized;
+    "#,
+        expect![[r#"
+            *Foo*
+
+            ```rust
+            ra_test_fixture
+            ```
+
+            ```rust
+            type Foo = impl Sized
+            ```
+
+            ---
+
+            contain types with destructors (drop glue)
+        "#]],
+    );
+    check(
+        r#"
+//- minicore: drop
+struct NeedsDrop;
+impl Drop for NeedsDrop {
+    fn drop(&mut self) {}
+}
+enum Enum {
+    A$0(&'static str),
+    B(NeedsDrop)
+}
+    "#,
+        expect![[r#"
+            *A*
+
+            ```rust
+            ra_test_fixture::Enum
+            ```
+
+            ```rust
+            A(&'static str)
+            ```
+
+            ---
+
+            size = 16 (0x10), align = 8, niches = 1
+
+            ---
+
+            does not contain types with destructors (drop glue)
+        "#]],
+    );
+    check(
+        r#"
+struct Foo$0<T>(T);
+    "#,
+        expect![[r#"
+            *Foo*
+
+            ```rust
+            ra_test_fixture
+            ```
+
+            ```rust
+            struct Foo<T>(T)
+            ```
+
+            ---
+
+            may contain types with destructors (drop glue) depending on type parameters; doesn't have a destructor
+        "#]],
+    );
+    check(
+        r#"
+//- minicore: copy
+struct Foo$0<T: Copy>(T);
+    "#,
+        expect![[r#"
+            *Foo*
+
+            ```rust
+            ra_test_fixture
+            ```
+
+            ```rust
+            struct Foo<T>(T)
+            where
+                T: Copy,
+            ```
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
+        "#]],
+    );
+    check(
+        r#"
+//- minicore: copy
+trait Trait {
+    type Assoc: Copy;
+}
+struct Foo$0<T: Trait>(T::Assoc);
+    "#,
+        expect![[r#"
+            *Foo*
+
+            ```rust
+            ra_test_fixture
+            ```
+
+            ```rust
+            struct Foo<T>(<T as Trait>::Assoc)
+            where
+                T: Trait,
+            ```
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
+        "#]],
+    );
+    check(
+        r#"
+#[rustc_coherence_is_core]
+
+#[lang = "manually_drop"]
+#[repr(transparent)]
+pub struct ManuallyDrop$0<T: ?Sized> {
+    value: T,
+}
+    "#,
+        expect![[r#"
+            *ManuallyDrop*
+
+            ```rust
+            ra_test_fixture
+            ```
+
+            ```rust
+            pub struct ManuallyDrop<T>
+            where
+                T: ?Sized,
+            {
+                value: T,
+            }
+            ```
+
+            ---
+
+            does not contain types with destructors (drop glue); doesn't have a destructor
+        "#]],
+    );
+}
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 d3b95750f7e..8522ef0a6d5 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
@@ -258,27 +258,25 @@ fn mode_and_needs_parens_for_adjustment_hints(
 fn needs_parens_for_adjustment_hints(expr: &ast::Expr, postfix: bool) -> (bool, bool) {
     let prec = expr.precedence();
     if postfix {
-        // postfix ops have higher precedence than any other operator, so we need to wrap
-        // any inner expression that is below (except for jumps if they don't have a value)
-        let needs_inner_parens = prec < ExprPrecedence::Unambiguous && {
-            prec != ExprPrecedence::Jump || !expr.is_ret_like_with_no_value()
-        };
+        let needs_inner_parens = prec.needs_parentheses_in(ExprPrecedence::Postfix);
         // given we are the higher precedence, no parent expression will have stronger requirements
         let needs_outer_parens = false;
         (needs_outer_parens, needs_inner_parens)
     } else {
-        // We need to wrap all binary like things, thats everything below prefix except for jumps
-        let needs_inner_parens = prec < ExprPrecedence::Prefix && prec != ExprPrecedence::Jump;
+        let needs_inner_parens = prec.needs_parentheses_in(ExprPrecedence::Prefix);
         let parent = expr
             .syntax()
             .parent()
             .and_then(ast::Expr::cast)
             // if we are already wrapped, great, no need to wrap again
             .filter(|it| !matches!(it, ast::Expr::ParenExpr(_)))
-            .map(|it| it.precedence());
+            .map(|it| it.precedence())
+            .filter(|&prec| prec != ExprPrecedence::Unambiguous);
+
         // if we have no parent, we don't need outer parens to disambiguate
         // otherwise anything with higher precedence than what we insert needs to wrap us
-        let needs_outer_parens = parent.is_some_and(|prec| prec > ExprPrecedence::Prefix);
+        let needs_outer_parens = parent
+            .is_some_and(|parent_prec| ExprPrecedence::Prefix.needs_parentheses_in(parent_prec));
         (needs_outer_parens, needs_inner_parens)
     }
 }
@@ -291,7 +289,7 @@ mod tests {
     };
 
     #[test]
-    fn adjustment_hints() {
+    fn adjustment_hints_prefix() {
         check_with_config(
             InlayHintsConfig { adjustment_hints: AdjustmentHints::Always, ..DISABLED_CONFIG },
             r#"
@@ -381,6 +379,8 @@ fn main() {
     &mut Struct[0];
        //^^^^^^(&mut $
        //^^^^^^)
+    let _: (&mut (),) = (&mut (),);
+                       //^^^^^^^&mut *
 }
 
 #[derive(Copy, Clone)]
@@ -472,6 +472,9 @@ fn main() {
   //^^^^^^.&
     &mut Struct[0];
        //^^^^^^.&mut
+    let _: (&mut (),) = (&mut (),);
+                       //^^^^^^^(
+                       //^^^^^^^).*.&mut
 }
 
 #[derive(Copy, Clone)]
diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs
index 27a1a510b4f..8ac1a96cc65 100644
--- a/src/tools/rust-analyzer/crates/ide/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs
@@ -104,7 +104,7 @@ pub use crate::{
     navigation_target::{NavigationTarget, TryToNav, UpmappingResult},
     references::ReferenceSearchResult,
     rename::RenameError,
-    runnables::{Runnable, RunnableKind, TestId},
+    runnables::{Runnable, RunnableKind, TestId, UpdateTest},
     signature_help::SignatureHelp,
     static_index::{
         StaticIndex, StaticIndexedFile, TokenId, TokenStaticData, VendoredLibrariesConfig,
diff --git a/src/tools/rust-analyzer/crates/ide/src/moniker.rs b/src/tools/rust-analyzer/crates/ide/src/moniker.rs
index 66ea49a98a0..25d12a4c0b4 100644
--- a/src/tools/rust-analyzer/crates/ide/src/moniker.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/moniker.rs
@@ -184,11 +184,11 @@ pub(crate) fn def_to_kind(db: &RootDatabase, def: Definition) -> SymbolInformati
 
     match def {
         Definition::Macro(it) => match it.kind(db) {
-            MacroKind::Declarative => Macro,
-            MacroKind::Derive => Attribute,
-            MacroKind::BuiltIn => Macro,
-            MacroKind::Attr => Attribute,
-            MacroKind::ProcMacro => Macro,
+            MacroKind::Derive
+            | MacroKind::DeriveBuiltIn
+            | MacroKind::AttrBuiltIn
+            | MacroKind::Attr => Attribute,
+            MacroKind::Declarative | MacroKind::DeclarativeBuiltIn | MacroKind::ProcMacro => Macro,
         },
         Definition::Field(..) | Definition::TupleField(..) => Field,
         Definition::Module(..) | Definition::Crate(..) => Module,
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 07553a87d28..41957bad7e0 100644
--- a/src/tools/rust-analyzer/crates/ide/src/static_index.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/static_index.rs
@@ -187,6 +187,7 @@ impl StaticIndex<'_> {
             max_fields_count: Some(5),
             max_enum_variants_count: Some(5),
             max_subst_ty_len: SubstTyLen::Unlimited,
+            show_drop_glue: true,
         };
         let tokens = tokens.filter(|token| {
             matches!(
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 1853e3a3407..519133e3ad1 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
@@ -7,7 +7,6 @@ mod escape;
 mod format;
 mod highlight;
 mod inject;
-mod macro_;
 
 mod html;
 #[cfg(test)]
@@ -15,14 +14,14 @@ mod tests;
 
 use std::ops::ControlFlow;
 
-use hir::{InRealFile, Name, Semantics};
+use hir::{HirFileIdExt, InFile, InRealFile, MacroFileIdExt, MacroKind, Name, Semantics};
 use ide_db::{FxHashMap, Ranker, RootDatabase, SymbolKind};
 use span::EditionedFileId;
 use syntax::{
     ast::{self, IsString},
     AstNode, AstToken, NodeOrToken,
     SyntaxKind::*,
-    SyntaxNode, TextRange, WalkEvent, T,
+    SyntaxNode, SyntaxToken, TextRange, WalkEvent, T,
 };
 
 use crate::{
@@ -30,7 +29,6 @@ use crate::{
         escape::{highlight_escape_byte, highlight_escape_char, highlight_escape_string},
         format::highlight_format_string,
         highlights::Highlights,
-        macro_::MacroHighlighter,
         tags::Highlight,
     },
     FileId, HlMod, HlOperator, HlPunct, HlTag,
@@ -221,7 +219,7 @@ pub(crate) fn highlight(
         Some(it) => it.krate(),
         None => return hl.to_vec(),
     };
-    traverse(&mut hl, &sema, config, file_id, &root, krate, range_to_highlight);
+    traverse(&mut hl, &sema, config, InRealFile::new(file_id, &root), krate, range_to_highlight);
     hl.to_vec()
 }
 
@@ -229,8 +227,7 @@ fn traverse(
     hl: &mut Highlights,
     sema: &Semantics<'_, RootDatabase>,
     config: HighlightConfig,
-    file_id: EditionedFileId,
-    root: &SyntaxNode,
+    InRealFile { file_id, value: root }: InRealFile<&SyntaxNode>,
     krate: hir::Crate,
     range_to_highlight: TextRange,
 ) {
@@ -252,18 +249,15 @@ fn traverse(
 
     let mut tt_level = 0;
     let mut attr_or_derive_item = None;
-    let mut current_macro: Option<ast::Macro> = None;
-    let mut macro_highlighter = MacroHighlighter::default();
 
     // FIXME: these are not perfectly accurate, we determine them by the real file's syntax tree
     // an attribute nested in a macro call will not emit `inside_attribute`
     let mut inside_attribute = false;
-    let mut inside_macro_call = false;
-    let mut inside_proc_macro_call = false;
 
     // Walk all nodes, keeping track of whether we are inside a macro or not.
     // If in macro, expand it first and highlight the expanded code.
-    for event in root.preorder_with_tokens() {
+    let mut preorder = root.preorder_with_tokens();
+    while let Some(event) = preorder.next() {
         use WalkEvent::{Enter, Leave};
 
         let range = match &event {
@@ -275,16 +269,11 @@ fn traverse(
             continue;
         }
 
-        // set macro and attribute highlighting states
         match event.clone() {
-            Enter(NodeOrToken::Node(node))
-                if current_macro.is_none() && ast::TokenTree::can_cast(node.kind()) =>
-            {
+            Enter(NodeOrToken::Node(node)) if ast::TokenTree::can_cast(node.kind()) => {
                 tt_level += 1;
             }
-            Leave(NodeOrToken::Node(node))
-                if current_macro.is_none() && ast::TokenTree::can_cast(node.kind()) =>
-            {
+            Leave(NodeOrToken::Node(node)) if ast::TokenTree::can_cast(node.kind()) => {
                 tt_level -= 1;
             }
             Enter(NodeOrToken::Node(node)) if ast::Attr::can_cast(node.kind()) => {
@@ -297,28 +286,14 @@ fn traverse(
             Enter(NodeOrToken::Node(node)) => {
                 if let Some(item) = ast::Item::cast(node.clone()) {
                     match item {
-                        ast::Item::MacroRules(mac) => {
-                            macro_highlighter.init();
-                            current_macro = Some(mac.into());
-                            continue;
-                        }
-                        ast::Item::MacroDef(mac) => {
-                            macro_highlighter.init();
-                            current_macro = Some(mac.into());
-                            continue;
-                        }
                         ast::Item::Fn(_) | ast::Item::Const(_) | ast::Item::Static(_) => {
                             bindings_shadow_count.clear()
                         }
-                        ast::Item::MacroCall(ref macro_call) => {
-                            inside_macro_call = true;
-                            inside_proc_macro_call = sema.is_proc_macro_call(macro_call);
-                        }
                         _ => (),
                     }
 
                     if attr_or_derive_item.is_none() {
-                        if sema.is_attr_macro_call(&item) {
+                        if sema.is_attr_macro_call(InFile::new(file_id.into(), &item)) {
                             attr_or_derive_item = Some(AttrOrDerive::Attr(item));
                         } else {
                             let adt = match item {
@@ -328,7 +303,10 @@ fn traverse(
                                 _ => None,
                             };
                             match adt {
-                                Some(adt) if sema.is_derive_annotated(&adt) => {
+                                Some(adt)
+                                    if sema
+                                        .is_derive_annotated(InFile::new(file_id.into(), &adt)) =>
+                                {
                                     attr_or_derive_item =
                                         Some(AttrOrDerive::Derive(ast::Item::from(adt)));
                                 }
@@ -340,25 +318,11 @@ fn traverse(
             }
             Leave(NodeOrToken::Node(node)) if ast::Item::can_cast(node.kind()) => {
                 match ast::Item::cast(node.clone()) {
-                    Some(ast::Item::MacroRules(mac)) => {
-                        assert_eq!(current_macro, Some(mac.into()));
-                        current_macro = None;
-                        macro_highlighter = MacroHighlighter::default();
-                    }
-                    Some(ast::Item::MacroDef(mac)) => {
-                        assert_eq!(current_macro, Some(mac.into()));
-                        current_macro = None;
-                        macro_highlighter = MacroHighlighter::default();
-                    }
                     Some(item)
                         if attr_or_derive_item.as_ref().is_some_and(|it| *it.item() == item) =>
                     {
                         attr_or_derive_item = None;
                     }
-                    Some(ast::Item::MacroCall(_)) => {
-                        inside_macro_call = false;
-                        inside_proc_macro_call = false;
-                    }
                     _ => (),
                 }
             }
@@ -379,12 +343,6 @@ fn traverse(
             }
         };
 
-        if current_macro.is_some() {
-            if let Some(tok) = element.as_token() {
-                macro_highlighter.advance(tok);
-            }
-        }
-
         let element = match element.clone() {
             NodeOrToken::Node(n) => match ast::NameLike::cast(n) {
                 Some(n) => NodeOrToken::Node(n),
@@ -392,7 +350,7 @@ fn traverse(
             },
             NodeOrToken::Token(t) => NodeOrToken::Token(t),
         };
-        let token = element.as_token().cloned();
+        let original_token = element.as_token().cloned();
 
         // Descending tokens into macros is expensive even if no descending occurs, so make sure
         // that we actually are in a position where descending is possible.
@@ -405,144 +363,52 @@ fn traverse(
 
         let descended_element = if in_macro {
             // Attempt to descend tokens into macro-calls.
-            let res = match element {
-                NodeOrToken::Token(token) if token.kind() != COMMENT => {
-                    let ranker = Ranker::from_token(&token);
-
-                    let mut t = None;
-                    let mut r = 0;
-                    sema.descend_into_macros_breakable(
-                        InRealFile::new(file_id, token.clone()),
-                        |tok, _ctx| {
-                            // FIXME: Consider checking ctx transparency for being opaque?
-                            let tok = tok.value;
-                            let my_rank = ranker.rank_token(&tok);
-
-                            if my_rank >= Ranker::MAX_RANK {
-                                // a rank of 0b1110 means that we have found a maximally interesting
-                                // token so stop early.
-                                t = Some(tok);
-                                return ControlFlow::Break(());
-                            }
-
-                            // r = r.max(my_rank);
-                            // t = Some(t.take_if(|_| r < my_rank).unwrap_or(tok));
-                            match &mut t {
-                                Some(prev) if r < my_rank => {
-                                    *prev = tok;
-                                    r = my_rank;
-                                }
-                                Some(_) => (),
-                                None => {
-                                    r = my_rank;
-                                    t = Some(tok)
-                                }
-                            }
-                            ControlFlow::Continue(())
-                        },
-                    );
-
-                    let token = t.unwrap_or(token);
-                    match token.parent().and_then(ast::NameLike::cast) {
-                        // Remap the token into the wrapping single token nodes
-                        Some(parent) => match (token.kind(), parent.syntax().kind()) {
-                            (T![self] | T![ident], NAME | NAME_REF) => NodeOrToken::Node(parent),
-                            (T![self] | T![super] | T![crate] | T![Self], NAME_REF) => {
-                                NodeOrToken::Node(parent)
-                            }
-                            (INT_NUMBER, NAME_REF) => NodeOrToken::Node(parent),
-                            (LIFETIME_IDENT, LIFETIME) => NodeOrToken::Node(parent),
-                            _ => NodeOrToken::Token(token),
-                        },
-                        None => NodeOrToken::Token(token),
-                    }
-                }
-                e => e,
-            };
-            res
+            match element {
+                NodeOrToken::Token(token) => descend_token(sema, InRealFile::new(file_id, token)),
+                n => InFile::new(file_id.into(), n),
+            }
         } else {
-            element
+            InFile::new(file_id.into(), element)
         };
 
-        // FIXME: do proper macro def highlighting https://github.com/rust-lang/rust-analyzer/issues/6232
-        // Skip metavariables from being highlighted to prevent keyword highlighting in them
-        if descended_element.as_token().and_then(|t| macro_highlighter.highlight(t)).is_some() {
-            continue;
+        // string highlight injections
+        if let (Some(original_token), Some(descended_token)) =
+            (original_token, descended_element.value.as_token())
+        {
+            let control_flow = string_injections(
+                hl,
+                sema,
+                config,
+                file_id,
+                krate,
+                original_token,
+                descended_token,
+            );
+            if control_flow.is_break() {
+                continue;
+            }
         }
 
-        // string highlight injections, note this does not use the descended element as proc-macros
-        // can rewrite string literals which invalidates our indices
-        if let (Some(token), Some(descended_token)) = (token, descended_element.as_token()) {
-            if ast::String::can_cast(token.kind()) && ast::String::can_cast(descended_token.kind())
-            {
-                let string = ast::String::cast(token);
-                let string_to_highlight = ast::String::cast(descended_token.clone());
-                if let Some((string, expanded_string)) = string.zip(string_to_highlight) {
-                    if string.is_raw()
-                        && inject::ra_fixture(hl, sema, config, &string, &expanded_string).is_some()
-                    {
-                        continue;
-                    }
-                    highlight_format_string(
-                        hl,
-                        sema,
-                        krate,
-                        &string,
-                        &expanded_string,
-                        range,
-                        file_id.edition(),
-                    );
-
-                    if !string.is_raw() {
-                        highlight_escape_string(hl, &string, range.start());
-                    }
-                }
-            } else if ast::ByteString::can_cast(token.kind())
-                && ast::ByteString::can_cast(descended_token.kind())
-            {
-                if let Some(byte_string) = ast::ByteString::cast(token) {
-                    if !byte_string.is_raw() {
-                        highlight_escape_string(hl, &byte_string, range.start());
-                    }
+        let edition = descended_element.file_id.edition(sema.db);
+        let element = match descended_element.value {
+            NodeOrToken::Node(name_like) => {
+                let hl = highlight::name_like(
+                    sema,
+                    krate,
+                    &mut bindings_shadow_count,
+                    config.syntactic_name_ref_highlighting,
+                    name_like,
+                    edition,
+                );
+                if hl.is_some() && !in_macro {
+                    // skip highlighting the contained token of our name-like node
+                    // as that would potentially overwrite our result
+                    preorder.skip_subtree();
                 }
-            } else if ast::CString::can_cast(token.kind())
-                && ast::CString::can_cast(descended_token.kind())
-            {
-                if let Some(c_string) = ast::CString::cast(token) {
-                    if !c_string.is_raw() {
-                        highlight_escape_string(hl, &c_string, range.start());
-                    }
-                }
-            } else if ast::Char::can_cast(token.kind())
-                && ast::Char::can_cast(descended_token.kind())
-            {
-                let Some(char) = ast::Char::cast(token) else {
-                    continue;
-                };
-
-                highlight_escape_char(hl, &char, range.start())
-            } else if ast::Byte::can_cast(token.kind())
-                && ast::Byte::can_cast(descended_token.kind())
-            {
-                let Some(byte) = ast::Byte::cast(token) else {
-                    continue;
-                };
-
-                highlight_escape_byte(hl, &byte, range.start())
+                hl
             }
-        }
-
-        let element = match descended_element {
-            NodeOrToken::Node(name_like) => highlight::name_like(
-                sema,
-                krate,
-                &mut bindings_shadow_count,
-                config.syntactic_name_ref_highlighting,
-                name_like,
-                file_id.edition(),
-            ),
             NodeOrToken::Token(token) => {
-                highlight::token(sema, token, file_id.edition()).zip(Some(None))
+                highlight::token(sema, token, edition, tt_level > 0).zip(Some(None))
             }
         };
         if let Some((mut highlight, binding_hash)) = element {
@@ -551,13 +417,6 @@ fn traverse(
                 // let the editor do its highlighting for these tokens instead
                 continue;
             }
-            if highlight.tag == HlTag::UnresolvedReference
-                && matches!(attr_or_derive_item, Some(AttrOrDerive::Derive(_)) if inside_attribute)
-            {
-                // do not emit unresolved references in derive helpers if the token mapping maps to
-                // something unresolvable. FIXME: There should be a way to prevent that
-                continue;
-            }
 
             // apply config filtering
             if !filter_by_config(&mut highlight, config) {
@@ -567,8 +426,9 @@ fn traverse(
             if inside_attribute {
                 highlight |= HlMod::Attribute
             }
-            if inside_macro_call && tt_level > 0 {
-                if inside_proc_macro_call {
+            if let Some(m) = descended_element.file_id.macro_file() {
+                if let MacroKind::ProcMacro | MacroKind::Attr | MacroKind::Derive = m.kind(sema.db)
+                {
                     highlight |= HlMod::ProcMacro
                 }
                 highlight |= HlMod::Macro
@@ -579,6 +439,99 @@ fn traverse(
     }
 }
 
+fn string_injections(
+    hl: &mut Highlights,
+    sema: &Semantics<'_, RootDatabase>,
+    config: HighlightConfig,
+    file_id: EditionedFileId,
+    krate: hir::Crate,
+    token: SyntaxToken,
+    descended_token: &SyntaxToken,
+) -> ControlFlow<()> {
+    if !matches!(token.kind(), STRING | BYTE_STRING | BYTE | CHAR | C_STRING) {
+        return ControlFlow::Continue(());
+    }
+    if let Some(string) = ast::String::cast(token.clone()) {
+        if let Some(descended_string) = ast::String::cast(descended_token.clone()) {
+            if string.is_raw()
+                && inject::ra_fixture(hl, sema, config, &string, &descended_string).is_some()
+            {
+                return ControlFlow::Break(());
+            }
+            highlight_format_string(hl, sema, krate, &string, &descended_string, file_id.edition());
+
+            if !string.is_raw() {
+                highlight_escape_string(hl, &string);
+            }
+        }
+    } else if let Some(byte_string) = ast::ByteString::cast(token.clone()) {
+        if !byte_string.is_raw() {
+            highlight_escape_string(hl, &byte_string);
+        }
+    } else if let Some(c_string) = ast::CString::cast(token.clone()) {
+        if !c_string.is_raw() {
+            highlight_escape_string(hl, &c_string);
+        }
+    } else if let Some(char) = ast::Char::cast(token.clone()) {
+        highlight_escape_char(hl, &char)
+    } else if let Some(byte) = ast::Byte::cast(token) {
+        highlight_escape_byte(hl, &byte)
+    }
+    ControlFlow::Continue(())
+}
+
+fn descend_token(
+    sema: &Semantics<'_, RootDatabase>,
+    token: InRealFile<SyntaxToken>,
+) -> InFile<NodeOrToken<ast::NameLike, SyntaxToken>> {
+    if token.value.kind() == COMMENT {
+        return token.map(NodeOrToken::Token).into();
+    }
+    let ranker = Ranker::from_token(&token.value);
+
+    let mut t = None;
+    let mut r = 0;
+    sema.descend_into_macros_breakable(token.clone(), |tok, _ctx| {
+        // FIXME: Consider checking ctx transparency for being opaque?
+        let my_rank = ranker.rank_token(&tok.value);
+
+        if my_rank >= Ranker::MAX_RANK {
+            // a rank of 0b1110 means that we have found a maximally interesting
+            // token so stop early.
+            t = Some(tok);
+            return ControlFlow::Break(());
+        }
+
+        // r = r.max(my_rank);
+        // t = Some(t.take_if(|_| r < my_rank).unwrap_or(tok));
+        match &mut t {
+            Some(prev) if r < my_rank => {
+                *prev = tok;
+                r = my_rank;
+            }
+            Some(_) => (),
+            None => {
+                r = my_rank;
+                t = Some(tok)
+            }
+        }
+        ControlFlow::Continue(())
+    });
+
+    let token = t.unwrap_or_else(|| token.into());
+    token.map(|token| match token.parent().and_then(ast::NameLike::cast) {
+        // Remap the token into the wrapping single token nodes
+        Some(parent) => match (token.kind(), parent.syntax().kind()) {
+            (T![ident] | T![self], NAME)
+            | (T![ident] | T![self] | T![super] | T![crate] | T![Self], NAME_REF)
+            | (INT_NUMBER, NAME_REF)
+            | (LIFETIME_IDENT, LIFETIME) => NodeOrToken::Node(parent),
+            _ => NodeOrToken::Token(token),
+        },
+        None => NodeOrToken::Token(token),
+    })
+}
+
 fn filter_by_config(highlight: &mut Highlight, config: HighlightConfig) -> bool {
     match &mut highlight.tag {
         HlTag::StringLiteral if !config.strings => return false,
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/escape.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/escape.rs
index 552ce9cd8c3..094f88f3a86 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/escape.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/escape.rs
@@ -4,12 +4,9 @@ use crate::{HlRange, HlTag};
 use syntax::ast::{Byte, Char, IsString};
 use syntax::{AstToken, TextRange, TextSize};
 
-pub(super) fn highlight_escape_string<T: IsString>(
-    stack: &mut Highlights,
-    string: &T,
-    start: TextSize,
-) {
+pub(super) fn highlight_escape_string<T: IsString>(stack: &mut Highlights, string: &T) {
     let text = string.text();
+    let start = string.syntax().text_range().start();
     string.escaped_char_ranges(&mut |piece_range, char| {
         if text[piece_range.start().into()..].starts_with('\\') {
             let highlight = match char {
@@ -25,7 +22,7 @@ pub(super) fn highlight_escape_string<T: IsString>(
     });
 }
 
-pub(super) fn highlight_escape_char(stack: &mut Highlights, char: &Char, start: TextSize) {
+pub(super) fn highlight_escape_char(stack: &mut Highlights, char: &Char) {
     if char.value().is_err() {
         // We do not emit invalid escapes highlighting here. The lexer would likely be in a bad
         // state and this token contains junk, since `'` is not a reliable delimiter (consider
@@ -42,11 +39,14 @@ pub(super) fn highlight_escape_char(stack: &mut Highlights, char: &Char, start:
         return;
     };
 
-    let range = TextRange::at(start + TextSize::from(1), TextSize::from(text.len() as u32));
+    let range = TextRange::at(
+        char.syntax().text_range().start() + TextSize::from(1),
+        TextSize::from(text.len() as u32),
+    );
     stack.add(HlRange { range, highlight: HlTag::EscapeSequence.into(), binding_hash: None })
 }
 
-pub(super) fn highlight_escape_byte(stack: &mut Highlights, byte: &Byte, start: TextSize) {
+pub(super) fn highlight_escape_byte(stack: &mut Highlights, byte: &Byte) {
     if byte.value().is_err() {
         // See `highlight_escape_char` for why no error highlighting here.
         return;
@@ -61,6 +61,9 @@ pub(super) fn highlight_escape_byte(stack: &mut Highlights, byte: &Byte, start:
         return;
     };
 
-    let range = TextRange::at(start + TextSize::from(2), TextSize::from(text.len() as u32));
+    let range = TextRange::at(
+        byte.syntax().text_range().start() + TextSize::from(2),
+        TextSize::from(text.len() as u32),
+    );
     stack.add(HlRange { range, highlight: HlTag::EscapeSequence.into(), binding_hash: None })
 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs
index 43a6bdad7e9..c63043621c2 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/format.rs
@@ -5,7 +5,7 @@ use ide_db::{
     SymbolKind,
 };
 use span::Edition;
-use syntax::{ast, TextRange};
+use syntax::{ast, AstToken};
 
 use crate::{
     syntax_highlighting::{highlight::highlight_def, highlights::Highlights},
@@ -18,15 +18,15 @@ pub(super) fn highlight_format_string(
     krate: hir::Crate,
     string: &ast::String,
     expanded_string: &ast::String,
-    range: TextRange,
     edition: Edition,
 ) {
     if is_format_string(expanded_string) {
+        let start = string.syntax().text_range().start();
         // FIXME: Replace this with the HIR info we have now.
         lex_format_specifiers(string, &mut |piece_range, kind| {
             if let Some(highlight) = highlight_format_specifier(kind) {
                 stack.add(HlRange {
-                    range: piece_range + range.start(),
+                    range: piece_range + start,
                     highlight: highlight.into(),
                     binding_hash: 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 194fde11601..127861a04bd 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
@@ -23,6 +23,7 @@ pub(super) fn token(
     sema: &Semantics<'_, RootDatabase>,
     token: SyntaxToken,
     edition: Edition,
+    in_tt: bool,
 ) -> Option<Highlight> {
     if let Some(comment) = ast::Comment::cast(token.clone()) {
         let h = HlTag::Comment;
@@ -40,13 +41,20 @@ pub(super) fn token(
         INT_NUMBER | FLOAT_NUMBER => HlTag::NumericLiteral.into(),
         BYTE => HlTag::ByteLiteral.into(),
         CHAR => HlTag::CharLiteral.into(),
-        IDENT if token.parent().and_then(ast::TokenTree::cast).is_some() => {
+        IDENT if in_tt => {
             // from this point on we are inside a token tree, this only happens for identifiers
             // that were not mapped down into macro invocations
             HlTag::None.into()
         }
         p if p.is_punct() => punctuation(sema, token, p),
-        k if k.is_keyword(edition) => keyword(sema, token, k)?,
+        k if k.is_keyword(edition) => {
+            if in_tt && token.prev_token().is_some_and(|t| t.kind() == T![$]) {
+                // we are likely within a macro definition where our keyword is a fragment name
+                HlTag::None.into()
+            } else {
+                keyword(sema, token, k)?
+            }
+        }
         _ => return None,
     };
     Some(highlight)
@@ -81,7 +89,7 @@ pub(super) fn name_like(
             Some(IdentClass::NameRefClass(NameRefClass::Definition(def, _))) => {
                 highlight_def(sema, krate, def, edition)
             }
-            // FIXME: Fallback for 'static and '_, as we do not resolve these yet
+            // FIXME: Fallback for '_, as we do not resolve these yet
             _ => SymbolKind::LifetimeParam.into(),
         },
     };
@@ -214,12 +222,6 @@ fn keyword(
         T![true] | T![false] => HlTag::BoolLiteral.into(),
         // crate is handled just as a token if it's in an `extern crate`
         T![crate] if parent_matches::<ast::ExternCrate>(&token) => h,
-        // self, crate, super and `Self` are handled as either a Name or NameRef already, unless they
-        // are inside unmapped token trees
-        T![self] | T![crate] | T![super] | T![Self] if parent_matches::<ast::NameRef>(&token) => {
-            return None
-        }
-        T![self] if parent_matches::<ast::Name>(&token) => return None,
         T![ref] => match token.parent().and_then(ast::IdentPat::cast) {
             Some(ident) if sema.is_unsafe_ident_pat(&ident) => h | HlMod::Unsafe,
             _ => h,
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/macro_.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/macro_.rs
deleted file mode 100644
index b441b4cc90e..00000000000
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/macro_.rs
+++ /dev/null
@@ -1,128 +0,0 @@
-//! Syntax highlighting for macro_rules!.
-use syntax::{SyntaxKind, SyntaxToken, TextRange, T};
-
-use crate::{HlRange, HlTag};
-
-#[derive(Default)]
-pub(super) struct MacroHighlighter {
-    state: Option<MacroMatcherParseState>,
-}
-
-impl MacroHighlighter {
-    pub(super) fn init(&mut self) {
-        self.state = Some(MacroMatcherParseState::default());
-    }
-
-    pub(super) fn advance(&mut self, token: &SyntaxToken) {
-        if let Some(state) = self.state.as_mut() {
-            update_macro_state(state, token);
-        }
-    }
-
-    pub(super) fn highlight(&self, token: &SyntaxToken) -> Option<HlRange> {
-        if let Some(state) = self.state.as_ref() {
-            if matches!(state.rule_state, RuleState::Matcher | RuleState::Expander) {
-                if let Some(range) = is_metavariable(token) {
-                    return Some(HlRange {
-                        range,
-                        highlight: HlTag::UnresolvedReference.into(),
-                        binding_hash: None,
-                    });
-                }
-            }
-        }
-        None
-    }
-}
-
-struct MacroMatcherParseState {
-    /// Opening and corresponding closing bracket of the matcher or expander of the current rule
-    paren_ty: Option<(SyntaxKind, SyntaxKind)>,
-    paren_level: usize,
-    rule_state: RuleState,
-    /// Whether we are inside the outer `{` `}` macro block that holds the rules
-    in_invoc_body: bool,
-}
-
-impl Default for MacroMatcherParseState {
-    fn default() -> Self {
-        MacroMatcherParseState {
-            paren_ty: None,
-            paren_level: 0,
-            in_invoc_body: false,
-            rule_state: RuleState::None,
-        }
-    }
-}
-
-#[derive(Copy, Clone, Debug, PartialEq)]
-enum RuleState {
-    Matcher,
-    Expander,
-    Between,
-    None,
-}
-
-impl RuleState {
-    fn transition(&mut self) {
-        *self = match self {
-            RuleState::Matcher => RuleState::Between,
-            RuleState::Expander => RuleState::None,
-            RuleState::Between => RuleState::Expander,
-            RuleState::None => RuleState::Matcher,
-        };
-    }
-}
-
-fn update_macro_state(state: &mut MacroMatcherParseState, tok: &SyntaxToken) {
-    if !state.in_invoc_body {
-        if tok.kind() == T!['{'] || tok.kind() == T!['('] {
-            state.in_invoc_body = true;
-        }
-        return;
-    }
-
-    match state.paren_ty {
-        Some((open, close)) => {
-            if tok.kind() == open {
-                state.paren_level += 1;
-            } else if tok.kind() == close {
-                state.paren_level -= 1;
-                if state.paren_level == 0 {
-                    state.rule_state.transition();
-                    state.paren_ty = None;
-                }
-            }
-        }
-        None => {
-            match tok.kind() {
-                T!['('] => {
-                    state.paren_ty = Some((T!['('], T![')']));
-                }
-                T!['{'] => {
-                    state.paren_ty = Some((T!['{'], T!['}']));
-                }
-                T!['['] => {
-                    state.paren_ty = Some((T!['['], T![']']));
-                }
-                _ => (),
-            }
-            if state.paren_ty.is_some() {
-                state.paren_level = 1;
-                state.rule_state.transition();
-            }
-        }
-    }
-}
-
-fn is_metavariable(token: &SyntaxToken) -> Option<TextRange> {
-    match token.kind() {
-        kind if kind.is_any_identifier() => {
-            if let Some(_dollar) = token.prev_token().filter(|t| t.kind() == T![$]) {
-                return Some(token.text_range());
-            }
-        }
-        _ => (),
-    };
-    None
-}
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html
index 15a6386aa3c..2bc22f960bd 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_asm.html
@@ -49,26 +49,26 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="keyword unsafe">unsafe</span> <span class="brace">{</span>
         <span class="keyword">let</span> <span class="variable declaration">foo</span> <span class="operator">=</span> <span class="numeric_literal">1</span><span class="semicolon">;</span>
         <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">o</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="semicolon">;</span>
-        <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>
+        <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis">(</span>
             <span class="string_literal macro">"%input = OpLoad _ {</span><span class="variable">0</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
             <span class="macro default_library library macro">concat</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"%result = "</span><span class="comma macro">,</span> <span class="string_literal macro">"bar"</span><span class="comma macro">,</span> <span class="string_literal macro">" _ %input"</span><span class="parenthesis macro">)</span><span class="comma macro">,</span>
             <span class="string_literal macro">"OpStore {</span><span class="variable">1</span><span class="string_literal macro">} %result"</span><span class="comma macro">,</span>
             <span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="operator macro">&</span><span class="variable macro">foo</span><span class="comma macro">,</span>
             <span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="operator macro">&</span><span class="keyword macro">mut</span> <span class="variable macro mutable">o</span><span class="comma macro">,</span>
-        <span class="parenthesis macro">)</span><span class="semicolon">;</span>
+        <span class="parenthesis">)</span><span class="semicolon">;</span>
 
         <span class="keyword">let</span> <span class="variable declaration">thread_id</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
-        <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"
+        <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"
             mov {</span><span class="variable">0</span><span class="string_literal macro">}, gs:[0x30]
             mov {</span><span class="variable">0</span><span class="string_literal macro">}, [{</span><span class="variable">0</span><span class="string_literal macro">}+0x48]
-        "</span><span class="comma macro">,</span> <span class="keyword macro">out</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="variable macro">thread_id</span><span class="comma macro">,</span> <span class="keyword macro">options</span><span class="parenthesis macro">(</span><span class="keyword macro">pure</span><span class="comma macro">,</span> <span class="keyword macro">readonly</span><span class="comma macro">,</span> <span class="keyword macro">nostack</span><span class="parenthesis macro">)</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+        "</span><span class="comma macro">,</span> <span class="keyword macro">out</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="variable macro">thread_id</span><span class="comma macro">,</span> <span class="keyword macro">options</span><span class="parenthesis macro">(</span><span class="keyword macro">pure</span><span class="comma macro">,</span> <span class="keyword macro">readonly</span><span class="comma macro">,</span> <span class="keyword macro">nostack</span><span class="parenthesis macro">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
         <span class="keyword">static</span> <span class="static declaration">UNMAP_BASE</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
         <span class="keyword const">const</span> <span class="constant const declaration">MEM_RELEASE</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
         <span class="keyword">static</span> <span class="static declaration">VirtualFree</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
         <span class="keyword const">const</span> <span class="constant const declaration">OffPtr</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
         <span class="keyword const">const</span> <span class="constant const declaration">OffFn</span><span class="colon">:</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
-        <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"
+        <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"
             push {</span><span class="variable">free_type</span><span class="string_literal macro">}
             push {</span><span class="variable">free_size</span><span class="string_literal macro">}
             push {</span><span class="variable">base</span><span class="string_literal macro">}
@@ -92,7 +92,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 
             <span class="variable declaration macro">base</span> <span class="operator macro">=</span> <span class="keyword macro">sym</span> <span class="static macro">UNMAP_BASE</span><span class="comma macro">,</span>
             <span class="keyword macro">options</span><span class="parenthesis macro">(</span><span class="keyword macro">noreturn</span><span class="parenthesis macro">)</span><span class="comma macro">,</span>
-        <span class="parenthesis macro">)</span><span class="semicolon">;</span>
+        <span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="brace">}</span>
 <span class="brace">}</span>
 <span class="comment">// taken from https://github.com/rust-embedded/cortex-m/blob/47921b51f8b960344fcfa1255a50a0d19efcde6d/cortex-m/src/asm.rs#L254-L274</span>
@@ -101,19 +101,19 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="comment">// Ensure thumb mode is set.</span>
     <span class="keyword">let</span> <span class="variable declaration">rv</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="value_param">rv</span> <span class="keyword">as</span> <span class="builtin_type">u32</span><span class="parenthesis">)</span> <span class="bitwise">|</span> <span class="numeric_literal">1</span><span class="semicolon">;</span>
     <span class="keyword">let</span> <span class="variable declaration">msp</span> <span class="operator">=</span> <span class="value_param">msp</span> <span class="keyword">as</span> <span class="builtin_type">u32</span><span class="semicolon">;</span>
-    <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>
+    <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis">(</span>
         <span class="string_literal macro">"mrs {</span><span class="variable">tmp</span><span class="string_literal macro">}, CONTROL"</span><span class="comma macro">,</span>
         <span class="string_literal macro">"bics {</span><span class="variable">tmp</span><span class="string_literal macro">}, {</span><span class="variable">spsel</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
         <span class="string_literal macro">"msr CONTROL, {</span><span class="variable">tmp</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
         <span class="string_literal macro">"isb"</span><span class="comma macro">,</span>
         <span class="string_literal macro">"msr MSP, {</span><span class="variable">msp</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
         <span class="string_literal macro">"bx {</span><span class="variable">rv</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
-        <span class="comment macro">// `out(reg) _` is not permitted in a `noreturn` asm! call,</span>
-        <span class="comment macro">// so instead use `in(reg) 0` and don't restore it afterwards.</span>
+        <span class="comment">// `out(reg) _` is not permitted in a `noreturn` asm! call,</span>
+        <span class="comment">// so instead use `in(reg) 0` and don't restore it afterwards.</span>
         <span class="variable declaration macro">tmp</span> <span class="operator macro">=</span> <span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="numeric_literal macro">0</span><span class="comma macro">,</span>
         <span class="variable declaration macro">spsel</span> <span class="operator macro">=</span> <span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="numeric_literal macro">2</span><span class="comma macro">,</span>
         <span class="variable declaration macro">msp</span> <span class="operator macro">=</span> <span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="variable macro">msp</span><span class="comma macro">,</span>
         <span class="variable declaration macro">rv</span> <span class="operator macro">=</span> <span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="variable macro">rv</span><span class="comma macro">,</span>
         <span class="keyword macro">options</span><span class="parenthesis macro">(</span><span class="keyword macro">noreturn</span><span class="comma macro">,</span> <span class="keyword macro">nomem</span><span class="comma macro">,</span> <span class="keyword macro">nostack</span><span class="parenthesis macro">)</span><span class="comma macro">,</span>
-    <span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="brace">}</span></code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html
index 485d44f97e1..e1d51dc0b71 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_attributes.html
@@ -45,20 +45,20 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
-<pre><code><span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute">allow</span><span class="parenthesis attribute">(</span><span class="none attribute">dead_code</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
-<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="tool_module attribute">rustfmt</span><span class="operator attribute">::</span><span class="tool_module attribute">skip</span><span class="attribute_bracket attribute">]</span>
+<pre><code><span class="attribute_bracket attribute macro proc_macro">#</span><span class="attribute_bracket attribute macro proc_macro">[</span><span class="builtin_attr attribute macro proc_macro">allow</span><span class="parenthesis attribute macro proc_macro">(</span><span class="none attribute macro proc_macro">dead_code</span><span class="parenthesis attribute macro proc_macro">)</span><span class="attribute_bracket attribute macro proc_macro">]</span>
+<span class="attribute_bracket attribute macro proc_macro">#</span><span class="attribute_bracket attribute macro proc_macro">[</span><span class="tool_module attribute macro proc_macro">rustfmt</span><span class="operator attribute macro proc_macro">::</span><span class="tool_module attribute macro proc_macro">skip</span><span class="attribute_bracket attribute macro proc_macro">]</span>
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="module attribute crate_root library">proc_macros</span><span class="operator attribute">::</span><span class="attribute attribute library">identity</span><span class="attribute_bracket attribute">]</span>
-<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="derive attribute default_library library">Default</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
+<span class="attribute_bracket attribute macro proc_macro">#</span><span class="attribute_bracket attribute macro proc_macro">[</span><span class="attribute attribute default_library library macro proc_macro">derive</span><span class="parenthesis attribute macro proc_macro">(</span><span class="derive attribute default_library library macro">Default</span><span class="parenthesis attribute macro proc_macro">)</span><span class="attribute_bracket attribute macro proc_macro">]</span>
 <span class="comment documentation">/// This is a doc comment</span>
 <span class="comment">// This is a normal comment</span>
 <span class="comment documentation">/// This is a doc comment</span>
-<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="derive attribute default_library library">Copy</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
+<span class="attribute_bracket attribute macro proc_macro">#</span><span class="attribute_bracket attribute macro proc_macro">[</span><span class="attribute attribute default_library library macro proc_macro">derive</span><span class="parenthesis attribute macro proc_macro">(</span><span class="derive attribute default_library library macro">Copy</span><span class="parenthesis attribute macro proc_macro">)</span><span class="attribute_bracket attribute macro proc_macro">]</span>
 <span class="comment">// This is another normal comment</span>
 <span class="comment documentation">/// This is another doc comment</span>
 <span class="comment">// This is another normal comment</span>
-<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="derive attribute default_library library">Copy</span><span class="comma attribute">,</span> <span class="unresolved_reference attribute">Unresolved</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
+<span class="attribute_bracket attribute macro proc_macro">#</span><span class="attribute_bracket attribute macro proc_macro">[</span><span class="attribute attribute default_library library macro proc_macro">derive</span><span class="parenthesis attribute macro proc_macro">(</span><span class="derive attribute default_library library macro">Copy</span><span class="comma attribute macro proc_macro">,</span> <span class="unresolved_reference attribute macro">Unresolved</span><span class="parenthesis attribute macro proc_macro">)</span><span class="attribute_bracket attribute macro proc_macro">]</span>
 <span class="comment">// The reason for these being here is to test AttrIds</span>
-<span class="keyword">enum</span> <span class="enum declaration">Foo</span> <span class="brace">{</span>
-    <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="derive_helper attribute default_library library">default</span><span class="attribute_bracket attribute">]</span>
-    <span class="enum_variant declaration">Bar</span>
-<span class="brace">}</span></code></pre>
\ No newline at end of file
+<span class="keyword macro proc_macro">enum</span> <span class="enum declaration macro proc_macro">Foo</span> <span class="brace macro proc_macro">{</span>
+    <span class="attribute_bracket attribute macro proc_macro">#</span><span class="attribute_bracket attribute macro proc_macro">[</span><span class="derive_helper attribute default_library library macro proc_macro">default</span><span class="attribute_bracket attribute macro proc_macro">]</span>
+    <span class="enum_variant declaration macro proc_macro">Bar</span>
+<span class="brace macro proc_macro">}</span></code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html
index c6eab90e42b..af29af3f03c 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_block_mod_items.html
@@ -53,9 +53,9 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="brace">}</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
-    <span class="macro public">foo</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="struct declaration macro public">Foo</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro public">foo</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="struct declaration macro public">Foo</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="keyword">mod</span> <span class="module declaration">module</span> <span class="brace">{</span>
-        <span class="macro public">foo</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="struct declaration macro public">Bar</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+        <span class="macro public">foo</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="struct declaration macro public">Bar</span><span class="parenthesis">)</span><span class="semicolon">;</span>
         <span class="keyword">fn</span> <span class="function declaration">func</span><span class="parenthesis">(</span><span class="punctuation">_</span><span class="colon">:</span> <span class="module">y</span><span class="operator">::</span><span class="struct public">Bar</span><span class="parenthesis">)</span> <span class="brace">{</span>
             <span class="keyword">mod</span> <span class="module declaration">inner</span> <span class="brace">{</span>
                 <span class="keyword">struct</span> <span class="struct declaration">Innerest</span><span class="angle">&lt;</span><span class="keyword">const</span> <span class="const_param const declaration">C</span><span class="colon">:</span> <span class="unresolved_reference">usize</span><span class="angle">&gt;</span> <span class="brace">{</span> <span class="field declaration">field</span><span class="colon">:</span> <span class="bracket">[</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> <span class="brace">{</span><span class="const_param const">C</span><span class="brace">}</span><span class="bracket">]</span> <span class="brace">}</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html
index 96cdb532dd5..6d8f6b3c6e3 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_const.html
@@ -57,7 +57,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="keyword const">const</span> <span class="brace">{</span>
         <span class="keyword">const</span> <span class="punctuation">|</span><span class="punctuation">|</span> <span class="brace">{</span><span class="brace">}</span>
     <span class="brace">}</span>
-    <span class="macro public">id</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>
+    <span class="macro public">id</span><span class="macro_bang">!</span><span class="parenthesis">(</span>
         <span class="constant const macro">CONST_ITEM</span><span class="semicolon macro">;</span>
         <span class="const_param const macro">CONST_PARAM</span><span class="semicolon macro">;</span>
         <span class="keyword const macro">const</span> <span class="brace macro">{</span>
@@ -65,7 +65,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
         <span class="brace macro">}</span><span class="semicolon macro">;</span>
         <span class="operator macro">&</span><span class="keyword macro">raw</span> <span class="keyword macro">const</span> <span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="semicolon macro">;</span>
         <span class="keyword macro">const</span>
-    <span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="operator">.</span><span class="method const consuming trait">assoc_const_method</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 <span class="keyword">trait</span> <span class="trait declaration">ConstTrait</span> <span class="brace">{</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
index eb77c14c2a5..263e4545fb5 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
@@ -105,7 +105,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="variable declaration injected">foo</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span>
     <span class="comment documentation">///</span>
     <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="comment injected">// calls bar on foo</span>
-    <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="macro injected">assert</span><span class="macro_bang injected">!</span><span class="parenthesis injected macro">(</span><span class="none injected macro">foo</span><span class="operator injected macro">.</span><span class="none injected macro">bar</span><span class="parenthesis injected macro">(</span><span class="parenthesis injected macro">)</span><span class="parenthesis injected macro">)</span><span class="semicolon injected">;</span>
+    <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="macro injected">assert</span><span class="macro_bang injected">!</span><span class="parenthesis injected">(</span><span class="none injected">foo</span><span class="operator injected">.</span><span class="none injected">bar</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span>
     <span class="comment documentation">///</span>
     <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="variable declaration injected">bar</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="variable injected">foo</span><span class="operator injected">.</span><span class="field injected">bar</span><span class="none injected"> </span><span class="logical injected">||</span><span class="none injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="constant injected">bar</span><span class="semicolon injected">;</span>
     <span class="comment documentation">///</span>
@@ -156,8 +156,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="brace">}</span>
 
 <span class="comment documentation">/// ```</span>
-<span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">macro_rules</span><span class="macro_bang injected">!</span><span class="none injected"> </span><span class="macro declaration injected public">noop</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected"> </span><span class="parenthesis injected">(</span><span class="punctuation injected">$</span><span class="none injected">expr</span><span class="colon injected">:</span><span class="none injected">expr</span><span class="parenthesis injected">)</span><span class="none injected"> </span><span class="operator injected">=</span><span class="operator injected">&gt;</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected"> </span><span class="punctuation injected">$</span><span class="none injected">expr </span><span class="brace injected">}</span><span class="brace injected">}</span>
-<span class="comment documentation">///</span><span class="comment documentation"> </span><span class="macro injected public">noop</span><span class="macro_bang injected">!</span><span class="parenthesis injected macro">(</span><span class="numeric_literal injected macro">1</span><span class="parenthesis injected macro">)</span><span class="semicolon injected">;</span>
+<span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">macro_rules</span><span class="macro_bang injected">!</span><span class="none injected"> </span><span class="macro declaration injected public">noop</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected"> </span><span class="parenthesis injected">(</span><span class="punctuation injected">$</span><span class="none injected">expr</span><span class="colon injected">:</span><span class="none injected">expr</span><span class="parenthesis injected">)</span><span class="none injected"> </span><span class="operator injected">=</span><span class="operator injected">&gt;</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected"> </span><span class="punctuation injected">$</span><span class="none injected">expr</span><span class="none injected"> </span><span class="brace injected">}</span><span class="brace injected">}</span>
+<span class="comment documentation">///</span><span class="comment documentation"> </span><span class="macro injected public">noop</span><span class="macro_bang injected">!</span><span class="parenthesis injected">(</span><span class="numeric_literal injected macro">1</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span>
 <span class="comment documentation">/// ```</span>
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">noop</span> <span class="brace">{</span>
     <span class="parenthesis">(</span><span class="punctuation">$</span>expr<span class="colon">:</span>expr<span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span>
@@ -177,7 +177,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="comment documentation">///</span>
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute">cfg_attr</span><span class="parenthesis attribute">(</span><span class="none attribute">feature</span> <span class="operator attribute">=</span> <span class="string_literal attribute">"alloc"</span><span class="comma attribute">,</span> <span class="none attribute">doc</span> <span class="operator attribute">=</span> <span class="string_literal attribute">"```rust"</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute">cfg_attr</span><span class="parenthesis attribute">(</span><span class="none attribute">not</span><span class="parenthesis attribute">(</span><span class="none attribute">feature</span> <span class="operator attribute">=</span> <span class="string_literal attribute">"alloc"</span><span class="parenthesis attribute">)</span><span class="comma attribute">,</span> <span class="none attribute">doc</span> <span class="operator attribute">=</span> <span class="string_literal attribute">"```ignore"</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
-<span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="punctuation injected">_</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="function injected">example</span><span class="parenthesis injected">(</span><span class="operator injected">&</span><span class="module injected">alloc</span><span class="operator injected">::</span><span class="macro injected">vec</span><span class="macro_bang injected">!</span><span class="bracket injected macro">[</span><span class="numeric_literal injected macro">1</span><span class="comma injected macro">,</span><span class="none injected"> </span><span class="numeric_literal injected macro">2</span><span class="comma injected macro">,</span><span class="none injected"> </span><span class="numeric_literal injected macro">3</span><span class="bracket injected macro">]</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span>
+<span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">let</span><span class="none injected"> </span><span class="punctuation injected">_</span><span class="none injected"> </span><span class="operator injected">=</span><span class="none injected"> </span><span class="function injected">example</span><span class="parenthesis injected">(</span><span class="operator injected">&</span><span class="module injected">alloc</span><span class="operator injected">::</span><span class="macro injected">vec</span><span class="macro_bang injected">!</span><span class="bracket injected">[</span><span class="numeric_literal injected">1</span><span class="comma injected">,</span><span class="none injected"> </span><span class="numeric_literal injected">2</span><span class="comma injected">,</span><span class="none injected"> </span><span class="numeric_literal injected">3</span><span class="bracket injected">]</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span>
 <span class="comment documentation">/// ```</span>
 <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration public">mix_and_match</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
 
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
index 9477d0d1b87..eb532a5639d 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
@@ -78,7 +78,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 
 <span class="keyword">use</span> <span class="self_keyword crate_root public">self</span><span class="operator">::</span><span class="struct">FooCopy</span><span class="operator">::</span><span class="brace">{</span><span class="self_keyword">self</span> <span class="keyword">as</span> <span class="struct declaration">BarCopy</span><span class="brace">}</span><span class="semicolon">;</span>
 
-<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="derive attribute default_library library">Copy</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
+<span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="derive attribute default_library library macro">Copy</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
 <span class="keyword">struct</span> <span class="struct declaration">FooCopy</span> <span class="brace">{</span>
     <span class="field declaration">x</span><span class="colon">:</span> <span class="builtin_type">u32</span><span class="comma">,</span>
 <span class="brace">}</span>
@@ -151,7 +151,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="keyword">let</span> <span class="variable callable declaration">bar</span> <span class="operator">=</span> <span class="struct">Foo</span><span class="operator">::</span><span class="method associated consuming">baz</span><span class="semicolon">;</span>
 
     <span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="numeric_literal">-</span><span class="numeric_literal">42</span><span class="comma">,</span><span class="parenthesis">)</span><span class="semicolon">;</span>
-    <span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="operator">-</span><span class="variable">baz</span><span class="operator">.</span><span class="field">0</span><span class="semicolon">;</span>
+    <span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="operator">-</span><span class="variable">baz</span><span class="operator">.</span><span class="field library">0</span><span class="semicolon">;</span>
 
     <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="logical">!</span><span class="bool_literal">true</span><span class="semicolon">;</span>
 
@@ -170,7 +170,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="keyword">impl</span><span class="angle">&lt;</span><span class="type_param declaration">T</span><span class="angle">&gt;</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="type_param">T</span><span class="angle">&gt;</span> <span class="brace">{</span>
     <span class="keyword">fn</span> <span class="method associated consuming declaration">and</span><span class="angle">&lt;</span><span class="type_param declaration">U</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="self_keyword declaration">self</span><span class="comma">,</span> <span class="value_param declaration">other</span><span class="colon">:</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="type_param">U</span><span class="angle">&gt;</span><span class="parenthesis">)</span> <span class="operator">-&gt;</span> <span class="enum">Option</span><span class="angle">&lt;</span><span class="parenthesis">(</span><span class="type_param">T</span><span class="comma">,</span> <span class="type_param">U</span><span class="parenthesis">)</span><span class="angle">&gt;</span> <span class="brace">{</span>
         <span class="keyword control">match</span> <span class="value_param">other</span> <span class="brace">{</span>
-            <span class="enum_variant">None</span> <span class="operator">=&gt;</span> <span class="unresolved_reference">unimplemented</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="comma">,</span>
+            <span class="enum_variant">None</span> <span class="operator">=&gt;</span> <span class="unresolved_reference">unimplemented</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="comma">,</span>
             <span class="variable declaration">Nope</span> <span class="operator">=&gt;</span> <span class="variable">Nope</span><span class="comma">,</span>
         <span class="brace">}</span>
     <span class="brace">}</span>
@@ -184,7 +184,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="keyword async">async</span> <span class="keyword">fn</span> <span class="function async declaration">async_main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
     <span class="keyword">let</span> <span class="variable declaration">f1</span> <span class="operator">=</span> <span class="function async">learn_and_sing</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="keyword">let</span> <span class="variable declaration">f2</span> <span class="operator">=</span> <span class="unresolved_reference">dance</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
-    <span class="unresolved_reference">futures</span><span class="operator">::</span><span class="unresolved_reference">join</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">f1</span><span class="comma macro">,</span> <span class="none macro">f2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="unresolved_reference">futures</span><span class="operator">::</span><span class="unresolved_reference">join</span><span class="macro_bang">!</span><span class="parenthesis">(</span>f1<span class="comma">,</span> f2<span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 
 <span class="keyword">fn</span> <span class="function declaration">use_foo_items</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
@@ -196,7 +196,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="keyword">let</span> <span class="variable declaration">control_flow</span> <span class="operator">=</span> <span class="module crate_root library">foo</span><span class="operator">::</span><span class="function library">identity</span><span class="parenthesis">(</span><span class="module crate_root library">foo</span><span class="operator">::</span><span class="enum library">ControlFlow</span><span class="operator">::</span><span class="enum_variant library">Continue</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
     <span class="keyword control">if</span> <span class="variable">control_flow</span><span class="operator">.</span><span class="method consuming library">should_die</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
-        <span class="module crate_root library">foo</span><span class="operator">::</span><span class="unresolved_reference">die</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+        <span class="module crate_root library">foo</span><span class="operator">::</span><span class="unresolved_reference">die</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="brace">}</span>
 <span class="brace">}</span>
 
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
index 5fbed35192b..1f9422161de 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html
@@ -51,7 +51,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="function">fixture</span><span class="parenthesis">(</span><span class="string_literal">r#"</span><span class="none injected">
 </span><span class="keyword injected">trait</span><span class="none injected"> </span><span class="trait declaration injected">Foo</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected">
     </span><span class="keyword injected">fn</span><span class="none injected"> </span><span class="function associated declaration injected static trait">foo</span><span class="parenthesis injected">(</span><span class="parenthesis injected">)</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected">
-        </span><span class="unresolved_reference injected">println</span><span class="macro_bang injected">!</span><span class="parenthesis injected macro">(</span><span class="string_literal injected macro">"2 + 2 = {}"</span><span class="comma injected macro">,</span><span class="none injected"> </span><span class="numeric_literal injected macro">4</span><span class="parenthesis injected macro">)</span><span class="semicolon injected">;</span><span class="none injected">
+        </span><span class="unresolved_reference injected">println</span><span class="macro_bang injected">!</span><span class="parenthesis injected">(</span><span class="string_literal injected">"2 + 2 = {}"</span><span class="comma injected">,</span><span class="none injected"> </span><span class="numeric_literal injected">4</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span><span class="none injected">
     </span><span class="brace injected">}</span><span class="none injected">
 </span><span class="brace injected">}</span><span class="string_literal">"#</span>
     <span class="parenthesis">)</span><span class="semicolon">;</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_issue_18089.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_issue_18089.html
index 06817af1b1f..a846addba3f 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_issue_18089.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_issue_18089.html
@@ -46,8 +46,8 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
 </style>
 <pre><code><span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
-    <span class="macro public">template</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">template</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro public">template</span><span class="macro_bang">!</span><span class="parenthesis">(</span>template<span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="module attribute crate_root library">proc_macros</span><span class="operator attribute">::</span><span class="attribute attribute library">issue_18089</span><span class="attribute_bracket attribute">]</span>
-<span class="keyword">fn</span> <span class="macro declaration public">template</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span></code></pre>
\ No newline at end of file
+<span class="keyword macro proc_macro">fn</span> <span class="macro declaration macro proc_macro public">template</span><span class="parenthesis macro proc_macro">(</span><span class="parenthesis macro proc_macro">)</span> <span class="brace macro proc_macro">{</span><span class="brace macro proc_macro">}</span></code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html
index 2d3407dbcda..c3377614d72 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2015.html
@@ -54,21 +54,21 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="brace">}</span>
 
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">void</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span><span class="brace">}</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span>discard<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span><span class="brace">}</span>
 <span class="brace">}</span>
 
 <span class="keyword">struct</span> <span class="struct declaration">__</span> <span class="keyword">where</span> <span class="self_type_keyword">Self</span><span class="colon">:</span><span class="semicolon">;</span>
 <span class="keyword">fn</span> <span class="function declaration">__</span><span class="parenthesis">(</span><span class="punctuation">_</span><span class="colon">:</span> <span class="unresolved_reference">Self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">Self</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">Self</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
 <span class="comment">// edition dependent</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">try</span> <span class="none macro">async</span> <span class="none macro">await</span> <span class="none macro">gen</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="none macro">try</span> <span class="none macro">async</span> <span class="none macro">await</span> <span class="none macro">gen</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// edition and context dependent</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">dyn</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="none macro">dyn</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// builtin custom syntax</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">builtin</span> <span class="none macro">offset_of</span> <span class="none macro">format_args</span> <span class="none macro">asm</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="none macro">builtin</span> <span class="none macro">offset_of</span> <span class="none macro">format_args</span> <span class="none macro">asm</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// contextual</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">macro_rules</span><span class="comma macro">,</span> <span class="none macro">union</span><span class="comma macro">,</span> <span class="none macro">default</span><span class="comma macro">,</span> <span class="none macro">raw</span><span class="comma macro">,</span> <span class="none macro">auto</span><span class="comma macro">,</span> <span class="none macro">yeet</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="none macro">macro_rules</span><span class="comma macro">,</span> <span class="none macro">union</span><span class="comma macro">,</span> <span class="none macro">default</span><span class="comma macro">,</span> <span class="none macro">raw</span><span class="comma macro">,</span> <span class="none macro">auto</span><span class="comma macro">,</span> <span class="none macro">yeet</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// reserved</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">abstract</span> <span class="keyword macro">become</span> <span class="keyword macro">box</span> <span class="keyword macro">do</span> <span class="keyword macro">final</span> <span class="keyword macro">macro</span> <span class="keyword macro">override</span> <span class="keyword macro">priv</span> <span class="keyword macro">typeof</span> <span class="keyword macro">unsized</span> <span class="keyword macro">virtual</span> <span class="keyword control macro">yield</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>'static 'self 'unsafe<span class="parenthesis macro">)</span></code></pre>
\ No newline at end of file
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">abstract</span> <span class="keyword macro">become</span> <span class="keyword macro">box</span> <span class="keyword macro">do</span> <span class="keyword macro">final</span> <span class="keyword macro">macro</span> <span class="keyword macro">override</span> <span class="keyword macro">priv</span> <span class="keyword macro">typeof</span> <span class="keyword macro">unsized</span> <span class="keyword macro">virtual</span> <span class="keyword control macro">yield</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span>'static 'self 'unsafe<span class="parenthesis">)</span></code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html
index f8eb5d068a8..9b22500396b 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2018.html
@@ -54,21 +54,21 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="brace">}</span>
 
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">void</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span><span class="brace">}</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span>discard<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span><span class="brace">}</span>
 <span class="brace">}</span>
 
 <span class="keyword">struct</span> <span class="struct declaration">__</span> <span class="keyword">where</span> <span class="self_type_keyword">Self</span><span class="colon">:</span><span class="semicolon">;</span>
 <span class="keyword">fn</span> <span class="function declaration">__</span><span class="parenthesis">(</span><span class="punctuation">_</span><span class="colon">:</span> <span class="unresolved_reference">Self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">Self</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">Self</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
 <span class="comment">// edition dependent</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">try</span> <span class="keyword async macro">async</span> <span class="keyword async control macro">await</span> <span class="none macro">gen</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">try</span> <span class="keyword async macro">async</span> <span class="keyword async control macro">await</span> <span class="none macro">gen</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// edition and context dependent</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">dyn</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">dyn</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// builtin custom syntax</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">builtin</span> <span class="none macro">offset_of</span> <span class="none macro">format_args</span> <span class="none macro">asm</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="none macro">builtin</span> <span class="none macro">offset_of</span> <span class="none macro">format_args</span> <span class="none macro">asm</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// contextual</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">macro_rules</span><span class="comma macro">,</span> <span class="none macro">union</span><span class="comma macro">,</span> <span class="none macro">default</span><span class="comma macro">,</span> <span class="none macro">raw</span><span class="comma macro">,</span> <span class="none macro">auto</span><span class="comma macro">,</span> <span class="none macro">yeet</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="none macro">macro_rules</span><span class="comma macro">,</span> <span class="none macro">union</span><span class="comma macro">,</span> <span class="none macro">default</span><span class="comma macro">,</span> <span class="none macro">raw</span><span class="comma macro">,</span> <span class="none macro">auto</span><span class="comma macro">,</span> <span class="none macro">yeet</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// reserved</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">abstract</span> <span class="keyword macro">become</span> <span class="keyword macro">box</span> <span class="keyword macro">do</span> <span class="keyword macro">final</span> <span class="keyword macro">macro</span> <span class="keyword macro">override</span> <span class="keyword macro">priv</span> <span class="keyword macro">typeof</span> <span class="keyword macro">unsized</span> <span class="keyword macro">virtual</span> <span class="keyword control macro">yield</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>'static 'self 'unsafe<span class="parenthesis macro">)</span></code></pre>
\ No newline at end of file
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">abstract</span> <span class="keyword macro">become</span> <span class="keyword macro">box</span> <span class="keyword macro">do</span> <span class="keyword macro">final</span> <span class="keyword macro">macro</span> <span class="keyword macro">override</span> <span class="keyword macro">priv</span> <span class="keyword macro">typeof</span> <span class="keyword macro">unsized</span> <span class="keyword macro">virtual</span> <span class="keyword control macro">yield</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span>'static 'self 'unsafe<span class="parenthesis">)</span></code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html
index f8eb5d068a8..9b22500396b 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2021.html
@@ -54,21 +54,21 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="brace">}</span>
 
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">void</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span><span class="brace">}</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span>discard<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span><span class="brace">}</span>
 <span class="brace">}</span>
 
 <span class="keyword">struct</span> <span class="struct declaration">__</span> <span class="keyword">where</span> <span class="self_type_keyword">Self</span><span class="colon">:</span><span class="semicolon">;</span>
 <span class="keyword">fn</span> <span class="function declaration">__</span><span class="parenthesis">(</span><span class="punctuation">_</span><span class="colon">:</span> <span class="unresolved_reference">Self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">Self</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">Self</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
 <span class="comment">// edition dependent</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">try</span> <span class="keyword async macro">async</span> <span class="keyword async control macro">await</span> <span class="none macro">gen</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">try</span> <span class="keyword async macro">async</span> <span class="keyword async control macro">await</span> <span class="none macro">gen</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// edition and context dependent</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">dyn</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">dyn</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// builtin custom syntax</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">builtin</span> <span class="none macro">offset_of</span> <span class="none macro">format_args</span> <span class="none macro">asm</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="none macro">builtin</span> <span class="none macro">offset_of</span> <span class="none macro">format_args</span> <span class="none macro">asm</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// contextual</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">macro_rules</span><span class="comma macro">,</span> <span class="none macro">union</span><span class="comma macro">,</span> <span class="none macro">default</span><span class="comma macro">,</span> <span class="none macro">raw</span><span class="comma macro">,</span> <span class="none macro">auto</span><span class="comma macro">,</span> <span class="none macro">yeet</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="none macro">macro_rules</span><span class="comma macro">,</span> <span class="none macro">union</span><span class="comma macro">,</span> <span class="none macro">default</span><span class="comma macro">,</span> <span class="none macro">raw</span><span class="comma macro">,</span> <span class="none macro">auto</span><span class="comma macro">,</span> <span class="none macro">yeet</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// reserved</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">abstract</span> <span class="keyword macro">become</span> <span class="keyword macro">box</span> <span class="keyword macro">do</span> <span class="keyword macro">final</span> <span class="keyword macro">macro</span> <span class="keyword macro">override</span> <span class="keyword macro">priv</span> <span class="keyword macro">typeof</span> <span class="keyword macro">unsized</span> <span class="keyword macro">virtual</span> <span class="keyword control macro">yield</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>'static 'self 'unsafe<span class="parenthesis macro">)</span></code></pre>
\ No newline at end of file
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">abstract</span> <span class="keyword macro">become</span> <span class="keyword macro">box</span> <span class="keyword macro">do</span> <span class="keyword macro">final</span> <span class="keyword macro">macro</span> <span class="keyword macro">override</span> <span class="keyword macro">priv</span> <span class="keyword macro">typeof</span> <span class="keyword macro">unsized</span> <span class="keyword macro">virtual</span> <span class="keyword control macro">yield</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span>'static 'self 'unsafe<span class="parenthesis">)</span></code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html
index fca84017069..ac8353120e8 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_2024.html
@@ -54,21 +54,21 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="brace">}</span>
 
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">void</span> <span class="brace">{</span>
-    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span><span class="brace">}</span>
+    <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span>discard<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span><span class="brace">}</span>
 <span class="brace">}</span>
 
 <span class="keyword">struct</span> <span class="struct declaration">__</span> <span class="keyword">where</span> <span class="self_type_keyword">Self</span><span class="colon">:</span><span class="semicolon">;</span>
 <span class="keyword">fn</span> <span class="function declaration">__</span><span class="parenthesis">(</span><span class="punctuation">_</span><span class="colon">:</span> <span class="unresolved_reference">Self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">Self</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">Self</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
 <span class="comment">// edition dependent</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">try</span> <span class="keyword async macro">async</span> <span class="keyword async control macro">await</span> <span class="keyword macro">gen</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">try</span> <span class="keyword async macro">async</span> <span class="keyword async control macro">await</span> <span class="keyword macro">gen</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// edition and context dependent</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">dyn</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">dyn</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// builtin custom syntax</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">builtin</span> <span class="none macro">offset_of</span> <span class="none macro">format_args</span> <span class="none macro">asm</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="none macro">builtin</span> <span class="none macro">offset_of</span> <span class="none macro">format_args</span> <span class="none macro">asm</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// contextual</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">macro_rules</span><span class="comma macro">,</span> <span class="none macro">union</span><span class="comma macro">,</span> <span class="none macro">default</span><span class="comma macro">,</span> <span class="none macro">raw</span><span class="comma macro">,</span> <span class="none macro">auto</span><span class="comma macro">,</span> <span class="none macro">yeet</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="none macro">macro_rules</span><span class="comma macro">,</span> <span class="none macro">union</span><span class="comma macro">,</span> <span class="none macro">default</span><span class="comma macro">,</span> <span class="none macro">raw</span><span class="comma macro">,</span> <span class="none macro">auto</span><span class="comma macro">,</span> <span class="none macro">yeet</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="comment">// reserved</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="keyword macro">abstract</span> <span class="keyword macro">become</span> <span class="keyword macro">box</span> <span class="keyword macro">do</span> <span class="keyword macro">final</span> <span class="keyword macro">macro</span> <span class="keyword macro">override</span> <span class="keyword macro">priv</span> <span class="keyword macro">typeof</span> <span class="keyword macro">unsized</span> <span class="keyword macro">virtual</span> <span class="keyword control macro">yield</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>'static 'self 'unsafe<span class="parenthesis macro">)</span></code></pre>
\ No newline at end of file
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">abstract</span> <span class="keyword macro">become</span> <span class="keyword macro">box</span> <span class="keyword macro">do</span> <span class="keyword macro">final</span> <span class="keyword macro">macro</span> <span class="keyword macro">override</span> <span class="keyword macro">priv</span> <span class="keyword macro">typeof</span> <span class="keyword macro">unsized</span> <span class="keyword macro">virtual</span> <span class="keyword control macro">yield</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+<span class="macro public">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span>'static 'self 'unsafe<span class="parenthesis">)</span></code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_macros.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_macros.html
new file mode 100644
index 00000000000..694e54d2fa8
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_keywords_macros.html
@@ -0,0 +1,50 @@
+
+<style>
+body                { margin: 0; }
+pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
+
+.lifetime           { color: #DFAF8F; font-style: italic; }
+.label              { color: #DFAF8F; font-style: italic; }
+.comment            { color: #7F9F7F; }
+.documentation      { color: #629755; }
+.intra_doc_link     { font-style: italic; }
+.injected           { opacity: 0.65 ; }
+.struct, .enum      { color: #7CB8BB; }
+.enum_variant       { color: #BDE0F3; }
+.string_literal     { color: #CC9393; }
+.field              { color: #94BFF3; }
+.function           { color: #93E0E3; }
+.function.unsafe    { color: #BC8383; }
+.trait.unsafe       { color: #BC8383; }
+.operator.unsafe    { color: #BC8383; }
+.mutable.unsafe     { color: #BC8383; text-decoration: underline; }
+.keyword.unsafe     { color: #BC8383; font-weight: bold; }
+.macro.unsafe       { color: #BC8383; }
+.parameter          { color: #94BFF3; }
+.text               { color: #DCDCCC; }
+.type               { color: #7CB8BB; }
+.builtin_type       { color: #8CD0D3; }
+.type_param         { color: #DFAF8F; }
+.attribute          { color: #94BFF3; }
+.numeric_literal    { color: #BFEBBF; }
+.bool_literal       { color: #BFE6EB; }
+.macro              { color: #94BFF3; }
+.proc_macro         { color: #94BFF3; text-decoration: underline; }
+.derive             { color: #94BFF3; font-style: italic; }
+.module             { color: #AFD8AF; }
+.value_param        { color: #DCDCCC; }
+.variable           { color: #DCDCCC; }
+.format_specifier   { color: #CC696B; }
+.mutable            { text-decoration: underline; }
+.escape_sequence    { color: #94BFF3; }
+.keyword            { color: #F0DFAF; font-weight: bold; }
+.control            { font-style: italic; }
+.reference          { font-style: italic; font-weight: bold; }
+.const              { font-weight: bolder; }
+
+.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
+.unresolved_reference    { color: #FC5555; text-decoration: wavy underline; }
+</style>
+<pre><code><span class="module crate_root library">lib2015</span><span class="operator">::</span><span class="macro library">void_2015</span><span class="macro_bang">!</span><span class="parenthesis">(</span>try async await <span class="none macro">gen</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+<span class="module crate_root library">lib2024</span><span class="operator">::</span><span class="macro library">void_2024</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword macro">try</span> <span class="keyword async macro">async</span> <span class="keyword async control macro">await</span> <span class="none macro">gen</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+</code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
index f640a5e6ca7..f224435e961 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
@@ -47,21 +47,21 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 </style>
 <pre><code><span class="keyword">use</span> <span class="module crate_root library">proc_macros</span><span class="operator">::</span><span class="brace">{</span><span class="function library">mirror</span><span class="comma">,</span> <span class="function library">identity</span><span class="comma">,</span> <span class="derive library">DeriveIdentity</span><span class="brace">}</span><span class="semicolon">;</span>
 
-<span class="proc_macro library">mirror</span><span class="macro_bang">!</span> <span class="brace macro proc_macro">{</span>
+<span class="proc_macro library">mirror</span><span class="macro_bang">!</span> <span class="brace">{</span>
     <span class="brace macro proc_macro">{</span>
         <span class="comma macro proc_macro">,</span><span class="builtin_type macro proc_macro">i32</span> <span class="colon macro proc_macro">:</span><span class="field declaration macro proc_macro public">x</span> <span class="keyword macro proc_macro">pub</span>
         <span class="comma macro proc_macro">,</span><span class="builtin_type macro proc_macro">i32</span> <span class="colon macro proc_macro">:</span><span class="field declaration macro proc_macro public">y</span> <span class="keyword macro proc_macro">pub</span>
     <span class="brace macro proc_macro">}</span> <span class="struct declaration macro proc_macro">Foo</span> <span class="keyword macro proc_macro">struct</span>
-<span class="brace macro proc_macro">}</span>
+<span class="brace">}</span>
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">def_fn</span> <span class="brace">{</span>
     <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="brace">}</span>
 <span class="brace">}</span>
 
-<span class="macro public">def_fn</span><span class="macro_bang">!</span> <span class="brace macro">{</span>
+<span class="macro public">def_fn</span><span class="macro_bang">!</span> <span class="brace">{</span>
     <span class="keyword macro">fn</span> <span class="function declaration macro">bar</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span> <span class="operator macro">-</span><span class="operator macro">&gt;</span> <span class="builtin_type macro">u32</span> <span class="brace macro">{</span>
         <span class="numeric_literal macro">100</span>
     <span class="brace macro">}</span>
-<span class="brace macro">}</span>
+<span class="brace">}</span>
 
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration public">dont_color_me_braces</span> <span class="brace">{</span>
     <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="operator">&gt;</span> <span class="brace">{</span><span class="numeric_literal">0</span><span class="brace">}</span>
@@ -100,16 +100,16 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="brace">}</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 
-<span class="macro default_library library">include</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="macro default_library library macro">concat</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"foo/"</span><span class="comma macro">,</span> <span class="string_literal macro">"foo.rs"</span><span class="parenthesis macro">)</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+<span class="macro default_library library">include</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="macro default_library library macro">concat</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"foo/"</span><span class="comma macro">,</span> <span class="string_literal macro">"foo.rs"</span><span class="parenthesis macro">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
 <span class="keyword">struct</span> <span class="struct declaration">S</span><span class="angle">&lt;</span><span class="type_param declaration">T</span><span class="angle">&gt;</span><span class="parenthesis">(</span><span class="type_param">T</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
     <span class="keyword">struct</span> <span class="struct declaration">TestLocal</span><span class="semicolon">;</span>
     <span class="comment">// regression test, TestLocal here used to not resolve</span>
-    <span class="keyword">let</span> <span class="punctuation">_</span><span class="colon">:</span> <span class="struct">S</span><span class="angle">&lt;</span><span class="macro public">id</span><span class="macro_bang">!</span><span class="bracket macro">[</span><span class="struct macro">TestLocal</span><span class="bracket macro">]</span><span class="angle">&gt;</span><span class="semicolon">;</span>
+    <span class="keyword">let</span> <span class="punctuation">_</span><span class="colon">:</span> <span class="struct">S</span><span class="angle">&lt;</span><span class="macro public">id</span><span class="macro_bang">!</span><span class="bracket">[</span><span class="struct macro">TestLocal</span><span class="bracket">]</span><span class="angle">&gt;</span><span class="semicolon">;</span>
 
-    <span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="parenthesis macro">(</span><span class="numeric_literal macro">92</span><span class="comma macro">,</span><span class="parenthesis macro">)</span><span class="operator macro">.</span><span class="field library macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">dont_color_me_braces</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">noop</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="macro macro public">noop</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="parenthesis macro">(</span><span class="numeric_literal macro">92</span><span class="comma macro">,</span><span class="parenthesis macro">)</span><span class="operator macro">.</span><span class="field library macro">0</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">dont_color_me_braces</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">noop</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="macro macro public">noop</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 </code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
index 1794d7dbfe2..539c74f6b57 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
@@ -99,86 +99,86 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 
     <span class="keyword">let</span> <span class="variable declaration">a</span> <span class="operator">=</span> <span class="byte_literal">b'</span><span class="escape_sequence">\xFF</span><span class="byte_literal">'</span><span class="semicolon">;</span>
 
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="escape_sequence">{{</span><span class="string_literal macro">Hello</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="escape_sequence">{{</span><span class="string_literal macro">Hello</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="comment">// from https://doc.rust-lang.org/std/fmt/index.html</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>                 <span class="comment">// =&gt; "Hello"</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"world"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>   <span class="comment">// =&gt; "Hello, world!"</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"The number is </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>   <span class="comment">// =&gt; "The number is 1"</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">?</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="parenthesis macro">(</span><span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="numeric_literal macro">4</span><span class="parenthesis macro">)</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>          <span class="comment">// =&gt; "(3, 4)"</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">value</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">value</span><span class="operator macro">=</span><span class="numeric_literal macro">4</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>      <span class="comment">// =&gt; "4"</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>           <span class="comment">// =&gt; "1 2"</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">4</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">42</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>             <span class="comment">// =&gt; "0042" with leading zerosV</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>   <span class="comment">// =&gt; "2 1 1 2"</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">argument</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">argument</span> <span class="operator macro">=</span> <span class="string_literal macro">"test"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>   <span class="comment">// =&gt; "test"</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span> <span class="operator macro">=</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>          <span class="comment">// =&gt; "2 1"</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">a</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">c</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">b</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">a</span><span class="operator macro">=</span><span class="string_literal macro">"a"</span><span class="comma macro">,</span> <span class="variable declaration macro">b</span><span class="operator macro">=</span><span class="char_literal macro">'b'</span><span class="comma macro">,</span> <span class="variable declaration macro">c</span><span class="operator macro">=</span><span class="numeric_literal macro">3</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>  <span class="comment">// =&gt; "a 3 b"</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>                       <span class="comment">// =&gt; "{2}"</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">width</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="variable declaration macro">width</span> <span class="operator macro">=</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">&lt;</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">-</span><span class="format_specifier">&lt;</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">^</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">&gt;</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">+</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="variable">x</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">27</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">-</span><span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="numeric_literal">0</span><span class="numeric_literal">10</span><span class="variable">x</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">27</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span>    <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span>   <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="variable">number</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="variable">prec</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="variable declaration macro">prec</span> <span class="operator macro">=</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="variable declaration macro">number</span> <span class="operator macro">=</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 fractional digits"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span><span class="operator macro">=</span><span class="numeric_literal macro">1234.56</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 characters"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span><span class="operator macro">=</span><span class="string_literal macro">"1234.56"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">&gt;</span><span class="numeric_literal">8</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 right-aligned characters"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span><span class="operator macro">=</span><span class="string_literal macro">"1234.56"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello"</span><span class="parenthesis">)</span><span class="semicolon">;</span>                 <span class="comment">// =&gt; "Hello"</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"world"</span><span class="parenthesis">)</span><span class="semicolon">;</span>   <span class="comment">// =&gt; "Hello, world!"</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"The number is </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis">)</span><span class="semicolon">;</span>   <span class="comment">// =&gt; "The number is 1"</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">?</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="parenthesis macro">(</span><span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="numeric_literal macro">4</span><span class="parenthesis macro">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>          <span class="comment">// =&gt; "(3, 4)"</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">value</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">value</span><span class="operator macro">=</span><span class="numeric_literal macro">4</span><span class="parenthesis">)</span><span class="semicolon">;</span>      <span class="comment">// =&gt; "4"</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="numeric_literal macro">2</span><span class="parenthesis">)</span><span class="semicolon">;</span>           <span class="comment">// =&gt; "1 2"</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">4</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">42</span><span class="parenthesis">)</span><span class="semicolon">;</span>             <span class="comment">// =&gt; "0042" with leading zerosV</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="numeric_literal macro">2</span><span class="parenthesis">)</span><span class="semicolon">;</span>   <span class="comment">// =&gt; "2 1 1 2"</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">argument</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">argument</span> <span class="operator macro">=</span> <span class="string_literal macro">"test"</span><span class="parenthesis">)</span><span class="semicolon">;</span>   <span class="comment">// =&gt; "test"</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span> <span class="operator macro">=</span> <span class="numeric_literal macro">2</span><span class="parenthesis">)</span><span class="semicolon">;</span>          <span class="comment">// =&gt; "2 1"</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">a</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">c</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">b</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">a</span><span class="operator macro">=</span><span class="string_literal macro">"a"</span><span class="comma macro">,</span> <span class="variable declaration macro">b</span><span class="operator macro">=</span><span class="char_literal macro">'b'</span><span class="comma macro">,</span> <span class="variable declaration macro">c</span><span class="operator macro">=</span><span class="numeric_literal macro">3</span><span class="parenthesis">)</span><span class="semicolon">;</span>  <span class="comment">// =&gt; "a 3 b"</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">2</span><span class="parenthesis">)</span><span class="semicolon">;</span>                       <span class="comment">// =&gt; "{2}"</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">width</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="variable declaration macro">width</span> <span class="operator macro">=</span> <span class="numeric_literal macro">5</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">&lt;</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">-</span><span class="format_specifier">&lt;</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">^</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">&gt;</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">+</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="variable">x</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">27</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">-</span><span class="numeric_literal macro">5</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="numeric_literal">0</span><span class="numeric_literal">10</span><span class="variable">x</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">27</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span>    <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span>   <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="variable">number</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="variable">prec</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="variable declaration macro">prec</span> <span class="operator macro">=</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="variable declaration macro">number</span> <span class="operator macro">=</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 fractional digits"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span><span class="operator macro">=</span><span class="numeric_literal macro">1234.56</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 characters"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span><span class="operator macro">=</span><span class="string_literal macro">"1234.56"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">&gt;</span><span class="numeric_literal">8</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal macro">` has 3 right-aligned characters"</span><span class="comma macro">,</span> <span class="string_literal macro">"Hello"</span><span class="comma macro">,</span> <span class="numeric_literal macro">3</span><span class="comma macro">,</span> <span class="variable declaration macro">name</span><span class="operator macro">=</span><span class="string_literal macro">"1234.56"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
     <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">"{}"</span>
     <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">"{{}}"</span><span class="semicolon">;</span>
 
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="escape_sequence">{{</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro"> Hello"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro">Hello</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro"> Hello </span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro">Hello </span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro"> Hello</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="escape_sequence">{{</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro"> Hello"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello </span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro">Hello</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro"> Hello </span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro">Hello </span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="escape_sequence">{{</span><span class="string_literal macro"> Hello</span><span class="escape_sequence">}}</span><span class="string_literal macro">"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">r"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"world"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">r"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="string_literal macro">"world"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
     <span class="comment">// escape sequences</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello</span><span class="escape_sequence">\n</span><span class="string_literal macro">World"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="escape_sequence">\u{48}</span><span class="escape_sequence">\x65</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6F</span><span class="string_literal macro"> World"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"Hello</span><span class="escape_sequence">\n</span><span class="string_literal macro">World"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="escape_sequence">\u{48}</span><span class="escape_sequence">\x65</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6C</span><span class="escape_sequence">\x6F</span><span class="string_literal macro"> World"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
     <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">"</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x00</span><span class="escape_sequence">\x63</span><span class="invalid_escape_sequence">\xFF</span><span class="escape_sequence">\u{FF}</span><span class="escape_sequence">\n</span><span class="string_literal">"</span><span class="semicolon">;</span> <span class="comment">// invalid non-UTF8 escape sequences</span>
     <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">b"</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x28</span><span class="escape_sequence">\x00</span><span class="escape_sequence">\x63</span><span class="escape_sequence">\xFF</span><span class="invalid_escape_sequence">\u{FF}</span><span class="escape_sequence">\n</span><span class="string_literal">"</span><span class="semicolon">;</span> <span class="comment">// valid bytes, invalid unicodes</span>
     <span class="keyword">let</span> <span class="punctuation">_</span> <span class="operator">=</span> <span class="string_literal">c"</span><span class="escape_sequence">\u{FF}</span><span class="escape_sequence">\xFF</span><span class="string_literal">"</span><span class="semicolon">;</span> <span class="comment">// valid bytes, valid unicodes</span>
     <span class="keyword">let</span> <span class="variable declaration reference">backslash</span> <span class="operator">=</span> <span class="string_literal">r"\\"</span><span class="semicolon">;</span>
 
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="escape_sequence">\x41</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">A</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">ничоси</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">ничоси</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="escape_sequence">\x41</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">A</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">ничоси</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable declaration macro">ничоси</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 
-    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">x</span><span class="format_specifier">?</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> "</span><span class="comma macro">,</span> <span class="unresolved_reference macro">thingy</span><span class="comma macro">,</span> <span class="unresolved_reference macro">n2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro default_library library">panic</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"{}"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro default_library library">panic</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"more </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro default_library library">assert</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="bool_literal macro">true</span><span class="comma macro">,</span> <span class="string_literal macro">"{}"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro default_library library">assert</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="bool_literal macro">true</span><span class="comma macro">,</span> <span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> asdasd"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">toho</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"{}fmt"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro public">println</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">x</span><span class="format_specifier">?</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> "</span><span class="comma macro">,</span> <span class="unresolved_reference macro">thingy</span><span class="comma macro">,</span> <span class="unresolved_reference macro">n2</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro default_library library">panic</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"{}"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro default_library library">panic</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"more </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro default_library library">assert</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="bool_literal macro">true</span><span class="comma">,</span> <span class="string_literal macro">"{}"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro default_library library">assert</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="bool_literal macro">true</span><span class="comma">,</span> <span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> asdasd"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">toho</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"{}fmt"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="keyword">let</span> <span class="variable declaration">i</span><span class="colon">:</span> <span class="builtin_type">u64</span> <span class="operator">=</span> <span class="numeric_literal">3</span><span class="semicolon">;</span>
     <span class="keyword">let</span> <span class="variable declaration">o</span><span class="colon">:</span> <span class="builtin_type">u64</span><span class="semicolon">;</span>
-    <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span>
+    <span class="module crate_root default_library library">core</span><span class="operator">::</span><span class="module default_library library">arch</span><span class="operator">::</span><span class="macro default_library library unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis">(</span>
         <span class="string_literal macro">"mov {</span><span class="variable">0</span><span class="string_literal macro">}, {</span><span class="variable">1</span><span class="string_literal macro">}"</span><span class="comma macro">,</span>
         <span class="string_literal macro">"add {</span><span class="variable">0</span><span class="string_literal macro">}, 5"</span><span class="comma macro">,</span>
         <span class="keyword macro">out</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="variable macro">o</span><span class="comma macro">,</span>
         <span class="keyword control macro">in</span><span class="parenthesis macro">(</span><span class="reg library macro">reg</span><span class="parenthesis macro">)</span> <span class="variable macro">i</span><span class="comma macro">,</span>
-    <span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="parenthesis">)</span><span class="semicolon">;</span>
 
     <span class="keyword const">const</span> <span class="constant const declaration">CONSTANT</span><span class="colon">:</span> <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="colon">:</span>
     <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">m</span> <span class="operator">=</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
-    <span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="macro default_library library macro">concat</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"{}"</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="string_literal macro">"{}"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">backslash</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">CONSTANT</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">m</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="comma macro">,</span> <span class="macro default_library library macro">format_args</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="unresolved_reference macro">foo</span><span class="comma macro">,</span> <span class="string_literal macro">"bar"</span><span class="comma macro">,</span> <span class="macro macro public">toho</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-    <span class="macro public">reuse_twice</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">backslash</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
+    <span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="macro default_library library macro">concat</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"{}"</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="string_literal macro">"{}"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro default_library library">format_args</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">backslash</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">CONSTANT</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="variable">m</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="comma macro">,</span> <span class="macro default_library library macro">format_args</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="unresolved_reference macro">foo</span><span class="comma macro">,</span> <span class="string_literal macro">"bar"</span><span class="comma macro">,</span> <span class="macro macro public">toho</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="variable macro reference">backslash</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+    <span class="macro public">reuse_twice</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">backslash</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="brace">}</span></code></pre>
\ No newline at end of file
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
index d9beac30898..9a46d9f4025 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
@@ -92,13 +92,13 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="keyword">let</span> <span class="variable declaration">x</span> <span class="operator">=</span> <span class="operator">&</span><span class="numeric_literal">5</span> <span class="keyword">as</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="punctuation">_</span> <span class="keyword">as</span> <span class="keyword">*</span><span class="keyword">const</span> <span class="builtin_type">usize</span><span class="semicolon">;</span>
     <span class="keyword">let</span> <span class="variable declaration">u</span> <span class="operator">=</span> <span class="union">Union</span> <span class="brace">{</span> <span class="field">b</span><span class="colon">:</span> <span class="numeric_literal">0</span> <span class="brace">}</span><span class="semicolon">;</span>
 
-    <span class="macro public">id</span><span class="macro_bang">!</span> <span class="brace macro">{</span>
+    <span class="macro public">id</span><span class="macro_bang">!</span> <span class="brace">{</span>
         <span class="keyword macro unsafe">unsafe</span> <span class="brace macro">{</span> <span class="macro macro public unsafe">unsafe_deref</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span> <span class="brace macro">}</span>
-    <span class="brace macro">}</span><span class="semicolon">;</span>
+    <span class="brace">}</span><span class="semicolon">;</span>
 
     <span class="keyword unsafe">unsafe</span> <span class="brace">{</span>
-        <span class="macro public unsafe">unsafe_deref</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
-        <span class="macro public unsafe">id</span><span class="macro_bang">!</span> <span class="brace macro">{</span> <span class="macro macro public unsafe">unsafe_deref</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span> <span class="brace macro">}</span><span class="semicolon">;</span>
+        <span class="macro public unsafe">unsafe_deref</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
+        <span class="macro public unsafe">id</span><span class="macro_bang">!</span> <span class="brace">{</span> <span class="macro macro public unsafe">unsafe_deref</span><span class="macro_bang macro">!</span><span class="parenthesis macro">(</span><span class="parenthesis macro">)</span> <span class="brace">}</span><span class="semicolon">;</span>
 
         <span class="comment">// unsafe fn and method calls</span>
         <span class="function unsafe">unsafe_fn</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span>
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
index 3775265f234..e48ca86c46b 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
@@ -386,7 +386,7 @@ mod __ {
 }
 
 macro_rules! void {
-    ($($tt:tt)*) => {}
+    ($($tt:tt)*) => {discard!($($tt:tt)*)}
 }
 
 struct __ where Self:;
@@ -412,6 +412,31 @@ void!('static 'self 'unsafe)
 }
 
 #[test]
+fn test_keyword_macro_edition_highlighting() {
+    check_highlighting(
+        r#"
+//- /main.rs crate:main edition:2018 deps:lib2015,lib2024
+lib2015::void_2015!(try async await gen);
+lib2024::void_2024!(try async await gen);
+//- /lib2015.rs crate:lib2015 edition:2015
+#[macro_export]
+macro_rules! void_2015 {
+    ($($tt:tt)*) => {discard!($($tt:tt)*)}
+}
+
+//- /lib2024.rs crate:lib2024 edition:2024
+#[macro_export]
+macro_rules! void_2024 {
+    ($($tt:tt)*) => {discard!($($tt:tt)*)}
+}
+
+"#,
+        expect_file![format!("./test_data/highlight_keywords_macros.html")],
+        false,
+    );
+}
+
+#[test]
 fn test_string_highlighting() {
     // The format string detection is based on macro-expansion,
     // thus, we have to copy the macro definition from `std`
diff --git a/src/tools/rust-analyzer/crates/intern/Cargo.toml b/src/tools/rust-analyzer/crates/intern/Cargo.toml
index c0358ef929b..397eba09296 100644
--- a/src/tools/rust-analyzer/crates/intern/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/intern/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 
 [dependencies]
diff --git a/src/tools/rust-analyzer/crates/mbe/Cargo.toml b/src/tools/rust-analyzer/crates/mbe/Cargo.toml
index b37d57f2801..e6fbb298ebd 100644
--- a/src/tools/rust-analyzer/crates/mbe/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/mbe/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 cov-mark = "2.0.0-pre.1"
diff --git a/src/tools/rust-analyzer/crates/mbe/src/parser.rs b/src/tools/rust-analyzer/crates/mbe/src/parser.rs
index 16d55492a04..0a670053c98 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/parser.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/parser.rs
@@ -13,8 +13,8 @@ use crate::ParseError;
 /// Consider
 ///
 /// ```
-/// macro_rules! an_macro {
-///     ($x:expr + $y:expr) => ($y * $x)
+/// macro_rules! a_macro {
+///     ($x:expr, $y:expr) => ($y * $x)
 /// }
 /// ```
 ///
diff --git a/src/tools/rust-analyzer/crates/parser/Cargo.toml b/src/tools/rust-analyzer/crates/parser/Cargo.toml
index 48436ec71f7..a36a39dbee6 100644
--- a/src/tools/rust-analyzer/crates/parser/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/parser/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 drop_bomb = "0.1.5"
diff --git a/src/tools/rust-analyzer/crates/parser/src/input.rs b/src/tools/rust-analyzer/crates/parser/src/input.rs
index c90b358cfbb..cabdff214df 100644
--- a/src/tools/rust-analyzer/crates/parser/src/input.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/input.rs
@@ -36,7 +36,7 @@ impl Input {
     /// the *previous* token was joint, with mbe, you know whether the *current*
     /// one is joint. This API allows for styles of usage:
     ///
-    /// ```
+    /// ```ignore
     /// // In text:
     /// tokens.was_joint(prev_joint);
     /// tokens.push(curr);
diff --git a/src/tools/rust-analyzer/crates/parser/src/lib.rs b/src/tools/rust-analyzer/crates/parser/src/lib.rs
index e461492cc6f..398ad7cf66c 100644
--- a/src/tools/rust-analyzer/crates/parser/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/lib.rs
@@ -59,7 +59,7 @@ pub use crate::{
 ///
 /// That is, for something like
 ///
-/// ```
+/// ```ignore
 /// quick_check! {
 ///    fn prop() {}
 /// }
diff --git a/src/tools/rust-analyzer/crates/parser/src/output.rs b/src/tools/rust-analyzer/crates/parser/src/output.rs
index 386d03a62cc..0ea15a656c1 100644
--- a/src/tools/rust-analyzer/crates/parser/src/output.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/output.rs
@@ -16,8 +16,9 @@ pub struct Output {
     /// 32-bit encoding of events. If LSB is zero, then that's an index into the
     /// error vector. Otherwise, it's one of the thee other variants, with data encoded as
     ///
-    ///     |16 bit kind|8 bit n_input_tokens|4 bit tag|4 bit leftover|
-    ///
+    /// ```text
+    /// |16 bit kind|8 bit n_input_tokens|4 bit tag|4 bit leftover|
+    /// ``````
     event: Vec<u32>,
     error: Vec<String>,
 }
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 79900425a17..e56e09eeb66 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
@@ -147,9 +147,6 @@ pub enum SyntaxKind {
     C_STRING,
     FLOAT_NUMBER,
     INT_NUMBER,
-    RAW_BYTE_STRING,
-    RAW_C_STRING,
-    RAW_STRING,
     STRING,
     COMMENT,
     ERROR,
@@ -343,9 +340,6 @@ impl SyntaxKind {
             | C_STRING
             | FLOAT_NUMBER
             | INT_NUMBER
-            | RAW_BYTE_STRING
-            | RAW_C_STRING
-            | RAW_STRING
             | STRING
             | ABI
             | ADT
@@ -898,18 +892,7 @@ impl SyntaxKind {
         )
     }
     pub fn is_literal(self) -> bool {
-        matches!(
-            self,
-            BYTE | BYTE_STRING
-                | CHAR
-                | C_STRING
-                | FLOAT_NUMBER
-                | INT_NUMBER
-                | RAW_BYTE_STRING
-                | RAW_C_STRING
-                | RAW_STRING
-                | STRING
-        )
+        matches!(self, BYTE | BYTE_STRING | CHAR | C_STRING | FLOAT_NUMBER | INT_NUMBER | STRING)
     }
     pub fn from_keyword(ident: &str, edition: Edition) -> Option<SyntaxKind> {
         let kw = match ident {
diff --git a/src/tools/rust-analyzer/crates/paths/Cargo.toml b/src/tools/rust-analyzer/crates/paths/Cargo.toml
index f0dafab70c1..4cc70726da0 100644
--- a/src/tools/rust-analyzer/crates/paths/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/paths/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 camino.workspace = true
diff --git a/src/tools/rust-analyzer/crates/paths/src/lib.rs b/src/tools/rust-analyzer/crates/paths/src/lib.rs
index 00842441616..3d722b1ff11 100644
--- a/src/tools/rust-analyzer/crates/paths/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/paths/src/lib.rs
@@ -232,7 +232,7 @@ impl AbsPath {
     /// - Removes trailing slashes: `/a/b/` becomes `/a/b`.
     ///
     /// # Example
-    /// ```
+    /// ```ignore
     /// # use paths::AbsPathBuf;
     /// let abs_path_buf = AbsPathBuf::assert("/a/../../b/.//c//".into());
     /// let normalized = abs_path_buf.normalize();
diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml
index dac8e094357..f5ba40a994b 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 serde.workspace = true
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 191535ac55e..d3b56b402ea 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 object.workspace = true
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml
index 7c6a1ba46b5..16fcc929620 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml
@@ -7,7 +7,6 @@ edition = "2021"
 license = "MIT OR Apache-2.0"
 
 [lib]
-doctest = false
 
 [build-dependencies]
 cargo_metadata = "0.18.1"
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/Cargo.toml
index fa189752b76..fb98d758a8b 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/Cargo.toml
@@ -6,7 +6,6 @@ edition = "2021"
 publish = false
 
 [lib]
-doctest = false
 proc-macro = true
 
 [dependencies]
diff --git a/src/tools/rust-analyzer/crates/profile/Cargo.toml b/src/tools/rust-analyzer/crates/profile/Cargo.toml
index 3179c810f69..9384fe26558 100644
--- a/src/tools/rust-analyzer/crates/profile/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/profile/Cargo.toml
@@ -10,14 +10,13 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 cfg-if = "1.0.0"
 libc.workspace = true
 jemalloc-ctl = { version = "0.5.0", package = "tikv-jemalloc-ctl", optional = true }
 
-[target.'cfg(target_os = "linux")'.dependencies]
+[target.'cfg(all(target_os = "linux", not(target_env = "ohos")))'.dependencies]
 perf-event = "=0.4.7"
 
 [target.'cfg(windows)'.dependencies]
diff --git a/src/tools/rust-analyzer/crates/profile/src/stop_watch.rs b/src/tools/rust-analyzer/crates/profile/src/stop_watch.rs
index 0a803959eed..9f3e636ef81 100644
--- a/src/tools/rust-analyzer/crates/profile/src/stop_watch.rs
+++ b/src/tools/rust-analyzer/crates/profile/src/stop_watch.rs
@@ -11,7 +11,7 @@ use crate::MemoryUsage;
 
 pub struct StopWatch {
     time: Instant,
-    #[cfg(target_os = "linux")]
+    #[cfg(all(target_os = "linux", not(target_env = "ohos")))]
     counter: Option<perf_event::Counter>,
     memory: MemoryUsage,
 }
@@ -24,7 +24,7 @@ pub struct StopWatchSpan {
 
 impl StopWatch {
     pub fn start() -> StopWatch {
-        #[cfg(target_os = "linux")]
+        #[cfg(all(target_os = "linux", not(target_env = "ohos")))]
         let counter = {
             // When debugging rust-analyzer using rr, the perf-related syscalls cause it to abort.
             // We allow disabling perf by setting the env var `RA_DISABLE_PERF`.
@@ -51,7 +51,7 @@ impl StopWatch {
         let time = Instant::now();
         StopWatch {
             time,
-            #[cfg(target_os = "linux")]
+            #[cfg(all(target_os = "linux", not(target_env = "ohos")))]
             counter,
             memory,
         }
@@ -60,10 +60,12 @@ impl StopWatch {
     pub fn elapsed(&mut self) -> StopWatchSpan {
         let time = self.time.elapsed();
 
-        #[cfg(target_os = "linux")]
+        #[cfg(all(target_os = "linux", not(target_env = "ohos")))]
         let instructions = self.counter.as_mut().and_then(|it| {
             it.read().map_err(|err| eprintln!("Failed to read perf counter: {err}")).ok()
         });
+        #[cfg(all(target_os = "linux", target_env = "ohos"))]
+        let instructions = None;
         #[cfg(not(target_os = "linux"))]
         let instructions = None;
 
diff --git a/src/tools/rust-analyzer/crates/project-model/Cargo.toml b/src/tools/rust-analyzer/crates/project-model/Cargo.toml
index ed647950e66..83def0e6b2a 100644
--- a/src/tools/rust-analyzer/crates/project-model/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/project-model/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 anyhow.workspace = true
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 b5f4e43a115..40ab8c53fae 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
@@ -594,7 +594,9 @@ impl CargoWorkspace {
             .filter_map(|package| {
                 let package = &self[package];
                 if package.is_member {
-                    Some(package.features.keys().cloned())
+                    Some(package.features.keys().cloned().chain(
+                        package.features.keys().map(|key| format!("{}/{key}", package.name)),
+                    ))
                 } else {
                     None
                 }
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 0c734474682..21a993c5a5e 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/lib.rs
@@ -262,7 +262,7 @@ fn parse_cfg(s: &str) -> Result<cfg::CfgAtom, String> {
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub enum RustSourceWorkspaceConfig {
     CargoMetadata(CargoMetadataConfig),
-    Stitched,
+    Json(ProjectJson),
 }
 
 impl Default for RustSourceWorkspaceConfig {
diff --git a/src/tools/rust-analyzer/crates/project-model/src/project_json.rs b/src/tools/rust-analyzer/crates/project-model/src/project_json.rs
index 2f9612e3a47..0282a714645 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/project_json.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/project_json.rs
@@ -65,6 +65,8 @@ pub struct ProjectJson {
     pub(crate) sysroot: Option<AbsPathBuf>,
     /// e.g. `path/to/sysroot/lib/rustlib/src/rust/library`
     pub(crate) sysroot_src: Option<AbsPathBuf>,
+    /// A nested project describing the layout of the sysroot
+    pub(crate) sysroot_project: Option<Box<ProjectJson>>,
     project_root: AbsPathBuf,
     /// The path to the rust-project.json file. May be None if this
     /// data was generated by the discoverConfig command.
@@ -91,9 +93,16 @@ impl ProjectJson {
         data: ProjectJsonData,
     ) -> ProjectJson {
         let absolutize_on_base = |p| base.absolutize(p);
+        let sysroot_src = data.sysroot_src.map(absolutize_on_base);
+        let sysroot_project =
+            data.sysroot_project.zip(sysroot_src.clone()).map(|(sysroot_data, sysroot_src)| {
+                Box::new(ProjectJson::new(None, &sysroot_src, *sysroot_data))
+            });
+
         ProjectJson {
             sysroot: data.sysroot.map(absolutize_on_base),
-            sysroot_src: data.sysroot_src.map(absolutize_on_base),
+            sysroot_src,
+            sysroot_project,
             project_root: base.to_path_buf(),
             manifest,
             runnables: data.runnables.into_iter().map(Runnable::from).collect(),
@@ -330,6 +339,7 @@ pub enum RunnableKind {
 pub struct ProjectJsonData {
     sysroot: Option<Utf8PathBuf>,
     sysroot_src: Option<Utf8PathBuf>,
+    sysroot_project: Option<Box<ProjectJsonData>>,
     #[serde(default)]
     cfg_groups: FxHashMap<String, CfgList>,
     crates: Vec<CrateData>,
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 fb752fe47b3..1e3c5a94786 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
@@ -4,24 +4,17 @@
 //! 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::{self, Not},
-    path::Path,
-    process::Command,
-};
+use std::{env, fs, ops::Not, path::Path, process::Command};
 
 use anyhow::{format_err, Result};
-use base_db::CrateName;
 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::{
-    cargo_workspace::CargoMetadataConfig, utf8_stdout, CargoWorkspace, ManifestPath,
+    cargo_workspace::CargoMetadataConfig, utf8_stdout, CargoWorkspace, ManifestPath, ProjectJson,
     RustSourceWorkspaceConfig,
 };
 
@@ -36,58 +29,10 @@ pub struct Sysroot {
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub enum RustLibSrcWorkspace {
     Workspace(CargoWorkspace),
-    Stitched(Stitched),
+    Json(ProjectJson),
     Empty,
 }
 
-#[derive(Debug, Clone, Eq, PartialEq)]
-pub struct Stitched {
-    crates: Arena<RustLibSrcCrateData>,
-}
-
-impl ops::Index<RustLibSrcCrate> for Stitched {
-    type Output = RustLibSrcCrateData;
-    fn index(&self, index: RustLibSrcCrate) -> &RustLibSrcCrateData {
-        &self.crates[index]
-    }
-}
-
-impl Stitched {
-    pub(crate) fn public_deps(
-        &self,
-    ) -> impl Iterator<Item = (CrateName, RustLibSrcCrate, bool)> + '_ {
-        // core is added as a dependency before std in order to
-        // mimic rustcs dependency order
-        [("core", true), ("alloc", false), ("std", true), ("test", false)].into_iter().filter_map(
-            move |(name, prelude)| {
-                Some((CrateName::new(name).unwrap(), self.by_name(name)?, prelude))
-            },
-        )
-    }
-
-    pub(crate) fn proc_macro(&self) -> Option<RustLibSrcCrate> {
-        self.by_name("proc_macro")
-    }
-
-    pub(crate) fn crates(&self) -> impl ExactSizeIterator<Item = RustLibSrcCrate> + '_ {
-        self.crates.iter().map(|(id, _data)| id)
-    }
-
-    fn by_name(&self, name: &str) -> Option<RustLibSrcCrate> {
-        let (id, _data) = self.crates.iter().find(|(_id, data)| data.name == name)?;
-        Some(id)
-    }
-}
-
-pub(crate) type RustLibSrcCrate = Idx<RustLibSrcCrateData>;
-
-#[derive(Debug, Clone, Eq, PartialEq)]
-pub(crate) struct RustLibSrcCrateData {
-    pub(crate) name: String,
-    pub(crate) root: ManifestPath,
-    pub(crate) deps: Vec<RustLibSrcCrate>,
-}
-
 impl Sysroot {
     pub const fn empty() -> Sysroot {
         Sysroot {
@@ -114,7 +59,7 @@ impl Sysroot {
     pub fn is_rust_lib_src_empty(&self) -> bool {
         match &self.workspace {
             RustLibSrcWorkspace::Workspace(ws) => ws.packages().next().is_none(),
-            RustLibSrcWorkspace::Stitched(stitched) => stitched.crates.is_empty(),
+            RustLibSrcWorkspace::Json(project_json) => project_json.n_crates() == 0,
             RustLibSrcWorkspace::Empty => true,
         }
     }
@@ -126,7 +71,7 @@ impl Sysroot {
     pub fn num_packages(&self) -> usize {
         match &self.workspace {
             RustLibSrcWorkspace::Workspace(ws) => ws.packages().count(),
-            RustLibSrcWorkspace::Stitched(c) => c.crates().count(),
+            RustLibSrcWorkspace::Json(project_json) => project_json.n_crates(),
             RustLibSrcWorkspace::Empty => 0,
         }
     }
@@ -252,52 +197,11 @@ impl Sysroot {
                     return Some(loaded);
                 }
             }
-        }
-        tracing::debug!("Stitching sysroot library: {src_root}");
-
-        let mut stitched = Stitched { crates: Arena::default() };
-
-        for path in SYSROOT_CRATES.trim().lines() {
-            let name = path.split('/').last().unwrap();
-            let root = [format!("{path}/src/lib.rs"), format!("lib{path}/lib.rs")]
-                .into_iter()
-                .map(|it| src_root.join(it))
-                .filter_map(|it| ManifestPath::try_from(it).ok())
-                .find(|it| fs::metadata(it).is_ok());
-
-            if let Some(root) = root {
-                stitched.crates.alloc(RustLibSrcCrateData {
-                    name: name.into(),
-                    root,
-                    deps: Vec::new(),
-                });
-            }
-        }
-
-        if let Some(std) = stitched.by_name("std") {
-            for dep in STD_DEPS.trim().lines() {
-                if let Some(dep) = stitched.by_name(dep) {
-                    stitched.crates[std].deps.push(dep)
-                }
-            }
-        }
-
-        if let Some(alloc) = stitched.by_name("alloc") {
-            for dep in ALLOC_DEPS.trim().lines() {
-                if let Some(dep) = stitched.by_name(dep) {
-                    stitched.crates[alloc].deps.push(dep)
-                }
-            }
+        } else if let RustSourceWorkspaceConfig::Json(project_json) = sysroot_source_config {
+            return Some(RustLibSrcWorkspace::Json(project_json.clone()));
         }
 
-        if let Some(proc_macro) = stitched.by_name("proc_macro") {
-            for dep in PROC_MACRO_DEPS.trim().lines() {
-                if let Some(dep) = stitched.by_name(dep) {
-                    stitched.crates[proc_macro].deps.push(dep)
-                }
-            }
-        }
-        Some(RustLibSrcWorkspace::Stitched(stitched))
+        None
     }
 
     pub fn set_workspace(&mut self, workspace: RustLibSrcWorkspace) {
@@ -308,7 +212,10 @@ impl Sysroot {
                     RustLibSrcWorkspace::Workspace(ws) => {
                         ws.packages().any(|p| ws[p].name == "core")
                     }
-                    RustLibSrcWorkspace::Stitched(stitched) => stitched.by_name("core").is_some(),
+                    RustLibSrcWorkspace::Json(project_json) => project_json
+                        .crates()
+                        .filter_map(|(_, krate)| krate.display_name.clone())
+                        .any(|name| name.canonical_name().as_str() == "core"),
                     RustLibSrcWorkspace::Empty => true,
                 };
                 if !has_core {
@@ -484,33 +391,3 @@ fn get_rust_lib_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> {
         None
     }
 }
-
-const SYSROOT_CRATES: &str = "
-alloc
-backtrace
-core
-panic_abort
-panic_unwind
-proc_macro
-profiler_builtins
-std
-stdarch/crates/std_detect
-test
-unwind";
-
-const ALLOC_DEPS: &str = "core";
-
-const STD_DEPS: &str = "
-alloc
-panic_unwind
-panic_abort
-core
-profiler_builtins
-unwind
-std_detect
-test";
-
-// core is required for our builtin derives to work in the proc_macro lib currently
-const PROC_MACRO_DEPS: &str = "
-std
-core";
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 54eb0e3478a..cfc666970bd 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/tests.rs
@@ -1,5 +1,3 @@
-use std::ops::Deref;
-
 use base_db::{CrateGraph, ProcMacroPaths};
 use cargo_metadata::Metadata;
 use cfg::{CfgAtom, CfgDiff};
@@ -226,18 +224,6 @@ fn rust_project_cfg_groups() {
 }
 
 #[test]
-fn rust_project_is_proc_macro_has_proc_macro_dep() {
-    let (crate_graph, _proc_macros) = load_rust_project("is-proc-macro-project.json");
-    // Since the project only defines one crate (outside the sysroot crates),
-    // it should be the one with the biggest Id.
-    let crate_id = crate_graph.iter().max().unwrap();
-    let crate_data = &crate_graph[crate_id];
-    // Assert that the project crate with `is_proc_macro` has a dependency
-    // on the proc_macro sysroot crate.
-    crate_data.dependencies.iter().find(|&dep| *dep.name.deref() == sym::proc_macro).unwrap();
-}
-
-#[test]
 fn crate_graph_dedup_identical() {
     let (mut crate_graph, proc_macros) = load_cargo("regex-metadata.json");
 
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 16b5bb11afa..2c9f41e828e 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
@@ -23,7 +23,7 @@ use crate::{
     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},
-    sysroot::{RustLibSrcCrate, RustLibSrcWorkspace},
+    sysroot::RustLibSrcWorkspace,
     toolchain_info::{rustc_cfg, target_data_layout, target_tuple, version, QueryConfig},
     CargoConfig, CargoWorkspace, CfgOverrides, InvocationStrategy, ManifestPath, Package,
     ProjectJson, ProjectManifest, RustSourceWorkspaceConfig, Sysroot, TargetData, TargetKind,
@@ -69,6 +69,7 @@ pub struct ProjectWorkspace {
 }
 
 #[derive(Clone)]
+#[allow(clippy::large_enum_variant)]
 pub enum ProjectWorkspaceKind {
     /// Project workspace was discovered by running `cargo metadata` and `rustc --print sysroot`.
     Cargo {
@@ -400,20 +401,17 @@ impl ProjectWorkspace {
     }
 
     pub fn load_inline(
-        project_json: ProjectJson,
+        mut project_json: ProjectJson,
         config: &CargoConfig,
         progress: &dyn Fn(String),
     ) -> ProjectWorkspace {
         progress("Discovering sysroot".to_owned());
         let mut sysroot =
             Sysroot::new(project_json.sysroot.clone(), project_json.sysroot_src.clone());
-        let loaded_sysroot = sysroot.load_workspace(&RustSourceWorkspaceConfig::Stitched);
-        if let Some(loaded_sysroot) = loaded_sysroot {
-            sysroot.set_workspace(loaded_sysroot);
-        }
 
         tracing::info!(workspace = %project_json.manifest_or_root(), src_root = ?sysroot.rust_lib_src_root(), root = ?sysroot.root(), "Using sysroot");
         progress("Querying project metadata".to_owned());
+        let sysroot_project = project_json.sysroot_project.take();
         let query_config = QueryConfig::Rustc(&sysroot, project_json.path().as_ref());
         let targets = target_tuple::get(query_config, config.target.as_deref(), &config.extra_env)
             .unwrap_or_default();
@@ -435,14 +433,33 @@ impl ProjectWorkspace {
                     &config.extra_env,
                 )
             });
-            thread::Result::Ok((toolchain.join()?, rustc_cfg.join()?, data_layout.join()?))
+            let loaded_sysroot = s.spawn(|| {
+                if let Some(sysroot_project) = sysroot_project {
+                    sysroot.load_workspace(&RustSourceWorkspaceConfig::Json(*sysroot_project))
+                } else {
+                    sysroot.load_workspace(&RustSourceWorkspaceConfig::CargoMetadata(
+                        sysroot_metadata_config(&config.extra_env, &targets),
+                    ))
+                }
+            });
+
+            thread::Result::Ok((
+                toolchain.join()?,
+                rustc_cfg.join()?,
+                data_layout.join()?,
+                loaded_sysroot.join()?,
+            ))
         });
 
-        let (toolchain, rustc_cfg, target_layout) = match join {
+        let (toolchain, rustc_cfg, target_layout, loaded_sysroot) = match join {
             Ok(it) => it,
             Err(e) => std::panic::resume_unwind(e),
         };
 
+        if let Some(loaded_sysroot) = loaded_sysroot {
+            sysroot.set_workspace(loaded_sysroot);
+        }
+
         ProjectWorkspace {
             kind: ProjectWorkspaceKind::Json(project_json),
             sysroot,
@@ -667,7 +684,15 @@ impl ProjectWorkspace {
                         Some(PackageRoot { is_local: false, include, exclude })
                     })
                     .collect(),
-                RustLibSrcWorkspace::Stitched(_) | RustLibSrcWorkspace::Empty => vec![],
+                RustLibSrcWorkspace::Json(project_json) => project_json
+                    .crates()
+                    .map(|(_, krate)| PackageRoot {
+                        is_local: false,
+                        include: krate.include.clone(),
+                        exclude: krate.exclude.clone(),
+                    })
+                    .collect(),
+                RustLibSrcWorkspace::Empty => vec![],
             };
 
             r.push(PackageRoot {
@@ -1069,8 +1094,7 @@ fn cargo_to_crate_graph(
 ) -> (CrateGraph, ProcMacroPaths) {
     let _p = tracing::info_span!("cargo_to_crate_graph").entered();
     let mut res = (CrateGraph::default(), ProcMacroPaths::default());
-    let crate_graph = &mut res.0;
-    let proc_macros = &mut res.1;
+    let (crate_graph, proc_macros) = &mut res;
     let (public_deps, libproc_macro) =
         sysroot_to_crate_graph(crate_graph, sysroot, rustc_cfg.clone(), load);
 
@@ -1490,6 +1514,69 @@ impl SysrootPublicDeps {
     }
 }
 
+fn extend_crate_graph_with_sysroot(
+    crate_graph: &mut CrateGraph,
+    mut sysroot_crate_graph: CrateGraph,
+    mut sysroot_proc_macros: ProcMacroPaths,
+) -> (SysrootPublicDeps, Option<CrateId>) {
+    let mut pub_deps = vec![];
+    let mut libproc_macro = None;
+    let diff = CfgDiff::new(vec![], vec![CfgAtom::Flag(sym::test.clone())]).unwrap();
+    for (cid, c) in sysroot_crate_graph.iter_mut() {
+        // uninject `test` flag so `core` keeps working.
+        Arc::make_mut(&mut c.cfg_options).apply_diff(diff.clone());
+        // patch the origin
+        if c.origin.is_local() {
+            let lang_crate = LangCrateOrigin::from(
+                c.display_name.as_ref().map_or("", |it| it.canonical_name().as_str()),
+            );
+            c.origin = CrateOrigin::Lang(lang_crate);
+            match lang_crate {
+                LangCrateOrigin::Test
+                | LangCrateOrigin::Alloc
+                | LangCrateOrigin::Core
+                | LangCrateOrigin::Std => pub_deps.push((
+                    CrateName::normalize_dashes(&lang_crate.to_string()),
+                    cid,
+                    !matches!(lang_crate, LangCrateOrigin::Test | LangCrateOrigin::Alloc),
+                )),
+                LangCrateOrigin::ProcMacro => libproc_macro = Some(cid),
+                LangCrateOrigin::Other => (),
+            }
+        }
+    }
+
+    let mut marker_set = vec![];
+    for &(_, cid, _) in pub_deps.iter() {
+        marker_set.extend(sysroot_crate_graph.transitive_deps(cid));
+    }
+    if let Some(cid) = libproc_macro {
+        marker_set.extend(sysroot_crate_graph.transitive_deps(cid));
+    }
+
+    marker_set.sort();
+    marker_set.dedup();
+
+    // Remove all crates except the ones we are interested in to keep the sysroot graph small.
+    let removed_mapping = sysroot_crate_graph.remove_crates_except(&marker_set);
+    sysroot_proc_macros = sysroot_proc_macros
+        .into_iter()
+        .filter_map(|(k, v)| Some((removed_mapping[k.into_raw().into_u32() as usize]?, v)))
+        .collect();
+    let mapping = crate_graph.extend(sysroot_crate_graph, &mut sysroot_proc_macros);
+
+    // Map the id through the removal mapping first, then through the crate graph extension mapping.
+    pub_deps.iter_mut().for_each(|(_, cid, _)| {
+        *cid = mapping[&removed_mapping[cid.into_raw().into_u32() as usize].unwrap()]
+    });
+    if let Some(libproc_macro) = &mut libproc_macro {
+        *libproc_macro =
+            mapping[&removed_mapping[libproc_macro.into_raw().into_u32() as usize].unwrap()];
+    }
+
+    (SysrootPublicDeps { deps: pub_deps }, libproc_macro)
+}
+
 fn sysroot_to_crate_graph(
     crate_graph: &mut CrateGraph,
     sysroot: &Sysroot,
@@ -1499,7 +1586,7 @@ fn sysroot_to_crate_graph(
     let _p = tracing::info_span!("sysroot_to_crate_graph").entered();
     match sysroot.workspace() {
         RustLibSrcWorkspace::Workspace(cargo) => {
-            let (mut cg, mut pm) = cargo_to_crate_graph(
+            let (cg, pm) = cargo_to_crate_graph(
                 load,
                 None,
                 cargo,
@@ -1520,113 +1607,32 @@ fn sysroot_to_crate_graph(
                 false,
             );
 
-            let mut pub_deps = vec![];
-            let mut libproc_macro = None;
-            let diff = CfgDiff::new(vec![], vec![CfgAtom::Flag(sym::test.clone())]).unwrap();
-            for (cid, c) in cg.iter_mut() {
-                // uninject `test` flag so `core` keeps working.
-                Arc::make_mut(&mut c.cfg_options).apply_diff(diff.clone());
-                // patch the origin
-                if c.origin.is_local() {
-                    let lang_crate = LangCrateOrigin::from(
-                        c.display_name.as_ref().map_or("", |it| it.canonical_name().as_str()),
-                    );
-                    c.origin = CrateOrigin::Lang(lang_crate);
-                    match lang_crate {
-                        LangCrateOrigin::Test
-                        | LangCrateOrigin::Alloc
-                        | LangCrateOrigin::Core
-                        | LangCrateOrigin::Std => pub_deps.push((
-                            CrateName::normalize_dashes(&lang_crate.to_string()),
-                            cid,
-                            !matches!(lang_crate, LangCrateOrigin::Test | LangCrateOrigin::Alloc),
-                        )),
-                        LangCrateOrigin::ProcMacro => libproc_macro = Some(cid),
-                        LangCrateOrigin::Other => (),
-                    }
-                }
-            }
-
-            let mut marker_set = vec![];
-            for &(_, cid, _) in pub_deps.iter() {
-                marker_set.extend(cg.transitive_deps(cid));
-            }
-            if let Some(cid) = libproc_macro {
-                marker_set.extend(cg.transitive_deps(cid));
-            }
-
-            marker_set.sort();
-            marker_set.dedup();
-
-            // Remove all crates except the ones we are interested in to keep the sysroot graph small.
-            let removed_mapping = cg.remove_crates_except(&marker_set);
-            let mapping = crate_graph.extend(cg, &mut pm);
-
-            // Map the id through the removal mapping first, then through the crate graph extension mapping.
-            pub_deps.iter_mut().for_each(|(_, cid, _)| {
-                *cid = mapping[&removed_mapping[cid.into_raw().into_u32() as usize].unwrap()]
-            });
-            if let Some(libproc_macro) = &mut libproc_macro {
-                *libproc_macro = mapping
-                    [&removed_mapping[libproc_macro.into_raw().into_u32() as usize].unwrap()];
-            }
-
-            (SysrootPublicDeps { deps: pub_deps }, libproc_macro)
+            extend_crate_graph_with_sysroot(crate_graph, cg, pm)
         }
-        RustLibSrcWorkspace::Stitched(stitched) => {
-            let cfg_options = Arc::new({
-                let mut cfg_options = CfgOptions::default();
-                cfg_options.extend(rustc_cfg);
-                cfg_options.insert_atom(sym::debug_assertions.clone());
-                cfg_options.insert_atom(sym::miri.clone());
-                cfg_options
-            });
-            let sysroot_crates: FxHashMap<RustLibSrcCrate, CrateId> = stitched
-                .crates()
-                .filter_map(|krate| {
-                    let file_id = load(&stitched[krate].root)?;
-
-                    let display_name = CrateDisplayName::from_canonical_name(&stitched[krate].name);
-                    let crate_id = crate_graph.add_crate_root(
-                        file_id,
-                        Edition::CURRENT_FIXME,
-                        Some(display_name),
-                        None,
-                        cfg_options.clone(),
-                        None,
-                        Env::default(),
-                        CrateOrigin::Lang(LangCrateOrigin::from(&*stitched[krate].name)),
-                        false,
-                        None,
-                    );
-                    Some((krate, crate_id))
-                })
-                .collect();
-
-            for from in stitched.crates() {
-                for &to in stitched[from].deps.iter() {
-                    let name = CrateName::new(&stitched[to].name).unwrap();
-                    if let (Some(&from), Some(&to)) =
-                        (sysroot_crates.get(&from), sysroot_crates.get(&to))
-                    {
-                        add_dep(crate_graph, from, name, to);
-                    }
-                }
-            }
-
-            let public_deps = SysrootPublicDeps {
-                deps: stitched
-                    .public_deps()
-                    .filter_map(|(name, idx, prelude)| {
-                        Some((name, *sysroot_crates.get(&idx)?, prelude))
-                    })
-                    .collect::<Vec<_>>(),
-            };
+        RustLibSrcWorkspace::Json(project_json) => {
+            let (cg, pm) = project_json_to_crate_graph(
+                rustc_cfg,
+                load,
+                project_json,
+                &Sysroot::empty(),
+                &FxHashMap::default(),
+                &CfgOverrides {
+                    global: CfgDiff::new(
+                        vec![
+                            CfgAtom::Flag(sym::debug_assertions.clone()),
+                            CfgAtom::Flag(sym::miri.clone()),
+                        ],
+                        vec![],
+                    )
+                    .unwrap(),
+                    ..Default::default()
+                },
+                false,
+            );
 
-            let libproc_macro =
-                stitched.proc_macro().and_then(|it| sysroot_crates.get(&it).copied());
-            (public_deps, libproc_macro)
+            extend_crate_graph_with_sysroot(crate_graph, cg, pm)
         }
+
         RustLibSrcWorkspace::Empty => (SysrootPublicDeps { deps: vec![] }, None),
     }
 }
diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/is-proc-macro-project.json b/src/tools/rust-analyzer/crates/project-model/test_data/is-proc-macro-project.json
deleted file mode 100644
index 5d500a4729f..00000000000
--- a/src/tools/rust-analyzer/crates/project-model/test_data/is-proc-macro-project.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-    "sysroot_src": null,
-    "crates": [
-        {
-            "display_name": "is_proc_macro",
-            "root_module": "$ROOT$src/lib.rs",
-            "edition": "2018",
-            "deps": [],
-            "is_workspace_member": true,
-            "is_proc_macro": true
-        }
-    ]
-}
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 9b4be19c41c..28ca4eb5348 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
@@ -3,417 +3,6 @@
         root_file_id: FileId(
             1,
         ),
-        edition: Edition2021,
-        version: None,
-        display_name: Some(
-            CrateDisplayName {
-                crate_name: CrateName(
-                    "alloc",
-                ),
-                canonical_name: "alloc",
-            },
-        ),
-        cfg_options: CfgOptions(
-            [
-                "debug_assertions",
-                "miri",
-                "true",
-            ],
-        ),
-        potential_cfg_options: None,
-        env: Env {
-            entries: {},
-        },
-        dependencies: [
-            Dependency {
-                crate_id: Idx::<CrateData>(1),
-                name: CrateName(
-                    "core",
-                ),
-                prelude: true,
-                sysroot: false,
-            },
-        ],
-        origin: Lang(
-            Alloc,
-        ),
-        is_proc_macro: false,
-        proc_macro_cwd: None,
-    },
-    1: CrateData {
-        root_file_id: FileId(
-            2,
-        ),
-        edition: Edition2021,
-        version: None,
-        display_name: Some(
-            CrateDisplayName {
-                crate_name: CrateName(
-                    "core",
-                ),
-                canonical_name: "core",
-            },
-        ),
-        cfg_options: CfgOptions(
-            [
-                "debug_assertions",
-                "miri",
-                "true",
-            ],
-        ),
-        potential_cfg_options: None,
-        env: Env {
-            entries: {},
-        },
-        dependencies: [],
-        origin: Lang(
-            Core,
-        ),
-        is_proc_macro: false,
-        proc_macro_cwd: None,
-    },
-    2: CrateData {
-        root_file_id: FileId(
-            3,
-        ),
-        edition: Edition2021,
-        version: None,
-        display_name: Some(
-            CrateDisplayName {
-                crate_name: CrateName(
-                    "panic_abort",
-                ),
-                canonical_name: "panic_abort",
-            },
-        ),
-        cfg_options: CfgOptions(
-            [
-                "debug_assertions",
-                "miri",
-                "true",
-            ],
-        ),
-        potential_cfg_options: None,
-        env: Env {
-            entries: {},
-        },
-        dependencies: [],
-        origin: Lang(
-            Other,
-        ),
-        is_proc_macro: false,
-        proc_macro_cwd: None,
-    },
-    3: CrateData {
-        root_file_id: FileId(
-            4,
-        ),
-        edition: Edition2021,
-        version: None,
-        display_name: Some(
-            CrateDisplayName {
-                crate_name: CrateName(
-                    "panic_unwind",
-                ),
-                canonical_name: "panic_unwind",
-            },
-        ),
-        cfg_options: CfgOptions(
-            [
-                "debug_assertions",
-                "miri",
-                "true",
-            ],
-        ),
-        potential_cfg_options: None,
-        env: Env {
-            entries: {},
-        },
-        dependencies: [],
-        origin: Lang(
-            Other,
-        ),
-        is_proc_macro: false,
-        proc_macro_cwd: None,
-    },
-    4: CrateData {
-        root_file_id: FileId(
-            5,
-        ),
-        edition: Edition2021,
-        version: None,
-        display_name: Some(
-            CrateDisplayName {
-                crate_name: CrateName(
-                    "proc_macro",
-                ),
-                canonical_name: "proc_macro",
-            },
-        ),
-        cfg_options: CfgOptions(
-            [
-                "debug_assertions",
-                "miri",
-                "true",
-            ],
-        ),
-        potential_cfg_options: None,
-        env: Env {
-            entries: {},
-        },
-        dependencies: [
-            Dependency {
-                crate_id: Idx::<CrateData>(6),
-                name: CrateName(
-                    "std",
-                ),
-                prelude: true,
-                sysroot: false,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(1),
-                name: CrateName(
-                    "core",
-                ),
-                prelude: true,
-                sysroot: false,
-            },
-        ],
-        origin: Lang(
-            ProcMacro,
-        ),
-        is_proc_macro: false,
-        proc_macro_cwd: None,
-    },
-    5: CrateData {
-        root_file_id: FileId(
-            6,
-        ),
-        edition: Edition2021,
-        version: None,
-        display_name: Some(
-            CrateDisplayName {
-                crate_name: CrateName(
-                    "profiler_builtins",
-                ),
-                canonical_name: "profiler_builtins",
-            },
-        ),
-        cfg_options: CfgOptions(
-            [
-                "debug_assertions",
-                "miri",
-                "true",
-            ],
-        ),
-        potential_cfg_options: None,
-        env: Env {
-            entries: {},
-        },
-        dependencies: [],
-        origin: Lang(
-            Other,
-        ),
-        is_proc_macro: false,
-        proc_macro_cwd: None,
-    },
-    6: CrateData {
-        root_file_id: FileId(
-            7,
-        ),
-        edition: Edition2021,
-        version: None,
-        display_name: Some(
-            CrateDisplayName {
-                crate_name: CrateName(
-                    "std",
-                ),
-                canonical_name: "std",
-            },
-        ),
-        cfg_options: CfgOptions(
-            [
-                "debug_assertions",
-                "miri",
-                "true",
-            ],
-        ),
-        potential_cfg_options: None,
-        env: Env {
-            entries: {},
-        },
-        dependencies: [
-            Dependency {
-                crate_id: Idx::<CrateData>(0),
-                name: CrateName(
-                    "alloc",
-                ),
-                prelude: true,
-                sysroot: false,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(3),
-                name: CrateName(
-                    "panic_unwind",
-                ),
-                prelude: true,
-                sysroot: false,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(2),
-                name: CrateName(
-                    "panic_abort",
-                ),
-                prelude: true,
-                sysroot: false,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(1),
-                name: CrateName(
-                    "core",
-                ),
-                prelude: true,
-                sysroot: false,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(5),
-                name: CrateName(
-                    "profiler_builtins",
-                ),
-                prelude: true,
-                sysroot: false,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(9),
-                name: CrateName(
-                    "unwind",
-                ),
-                prelude: true,
-                sysroot: false,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(7),
-                name: CrateName(
-                    "std_detect",
-                ),
-                prelude: true,
-                sysroot: false,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(8),
-                name: CrateName(
-                    "test",
-                ),
-                prelude: true,
-                sysroot: false,
-            },
-        ],
-        origin: Lang(
-            Std,
-        ),
-        is_proc_macro: false,
-        proc_macro_cwd: None,
-    },
-    7: CrateData {
-        root_file_id: FileId(
-            8,
-        ),
-        edition: Edition2021,
-        version: None,
-        display_name: Some(
-            CrateDisplayName {
-                crate_name: CrateName(
-                    "std_detect",
-                ),
-                canonical_name: "std_detect",
-            },
-        ),
-        cfg_options: CfgOptions(
-            [
-                "debug_assertions",
-                "miri",
-                "true",
-            ],
-        ),
-        potential_cfg_options: None,
-        env: Env {
-            entries: {},
-        },
-        dependencies: [],
-        origin: Lang(
-            Other,
-        ),
-        is_proc_macro: false,
-        proc_macro_cwd: None,
-    },
-    8: CrateData {
-        root_file_id: FileId(
-            9,
-        ),
-        edition: Edition2021,
-        version: None,
-        display_name: Some(
-            CrateDisplayName {
-                crate_name: CrateName(
-                    "test",
-                ),
-                canonical_name: "test",
-            },
-        ),
-        cfg_options: CfgOptions(
-            [
-                "debug_assertions",
-                "miri",
-                "true",
-            ],
-        ),
-        potential_cfg_options: None,
-        env: Env {
-            entries: {},
-        },
-        dependencies: [],
-        origin: Lang(
-            Test,
-        ),
-        is_proc_macro: false,
-        proc_macro_cwd: None,
-    },
-    9: CrateData {
-        root_file_id: FileId(
-            10,
-        ),
-        edition: Edition2021,
-        version: None,
-        display_name: Some(
-            CrateDisplayName {
-                crate_name: CrateName(
-                    "unwind",
-                ),
-                canonical_name: "unwind",
-            },
-        ),
-        cfg_options: CfgOptions(
-            [
-                "debug_assertions",
-                "miri",
-                "true",
-            ],
-        ),
-        potential_cfg_options: None,
-        env: Env {
-            entries: {},
-        },
-        dependencies: [],
-        origin: Lang(
-            Other,
-        ),
-        is_proc_macro: false,
-        proc_macro_cwd: None,
-    },
-    10: CrateData {
-        root_file_id: FileId(
-            11,
-        ),
         edition: Edition2018,
         version: None,
         display_name: Some(
@@ -438,48 +27,7 @@
         env: Env {
             entries: {},
         },
-        dependencies: [
-            Dependency {
-                crate_id: Idx::<CrateData>(1),
-                name: CrateName(
-                    "core",
-                ),
-                prelude: true,
-                sysroot: true,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(0),
-                name: CrateName(
-                    "alloc",
-                ),
-                prelude: false,
-                sysroot: true,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(6),
-                name: CrateName(
-                    "std",
-                ),
-                prelude: true,
-                sysroot: true,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(8),
-                name: CrateName(
-                    "test",
-                ),
-                prelude: false,
-                sysroot: true,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(4),
-                name: CrateName(
-                    "proc_macro",
-                ),
-                prelude: false,
-                sysroot: true,
-            },
-        ],
+        dependencies: [],
         origin: Local {
             repo: None,
             name: Some(
@@ -489,9 +37,9 @@
         is_proc_macro: false,
         proc_macro_cwd: None,
     },
-    11: CrateData {
+    1: CrateData {
         root_file_id: FileId(
-            11,
+            1,
         ),
         edition: Edition2018,
         version: None,
@@ -517,48 +65,7 @@
         env: Env {
             entries: {},
         },
-        dependencies: [
-            Dependency {
-                crate_id: Idx::<CrateData>(1),
-                name: CrateName(
-                    "core",
-                ),
-                prelude: true,
-                sysroot: true,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(0),
-                name: CrateName(
-                    "alloc",
-                ),
-                prelude: false,
-                sysroot: true,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(6),
-                name: CrateName(
-                    "std",
-                ),
-                prelude: true,
-                sysroot: true,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(8),
-                name: CrateName(
-                    "test",
-                ),
-                prelude: false,
-                sysroot: true,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(4),
-                name: CrateName(
-                    "proc_macro",
-                ),
-                prelude: false,
-                sysroot: true,
-            },
-        ],
+        dependencies: [],
         origin: Local {
             repo: None,
             name: Some(
diff --git a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
index 4c8e66e8e96..dde8d3023dc 100644
--- a/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
+++ b/src/tools/rust-analyzer/crates/project-model/test_data/output/rust_project_hello_world_project_model.txt
@@ -3,417 +3,6 @@
         root_file_id: FileId(
             1,
         ),
-        edition: Edition2021,
-        version: None,
-        display_name: Some(
-            CrateDisplayName {
-                crate_name: CrateName(
-                    "alloc",
-                ),
-                canonical_name: "alloc",
-            },
-        ),
-        cfg_options: CfgOptions(
-            [
-                "debug_assertions",
-                "miri",
-                "true",
-            ],
-        ),
-        potential_cfg_options: None,
-        env: Env {
-            entries: {},
-        },
-        dependencies: [
-            Dependency {
-                crate_id: Idx::<CrateData>(1),
-                name: CrateName(
-                    "core",
-                ),
-                prelude: true,
-                sysroot: false,
-            },
-        ],
-        origin: Lang(
-            Alloc,
-        ),
-        is_proc_macro: false,
-        proc_macro_cwd: None,
-    },
-    1: CrateData {
-        root_file_id: FileId(
-            2,
-        ),
-        edition: Edition2021,
-        version: None,
-        display_name: Some(
-            CrateDisplayName {
-                crate_name: CrateName(
-                    "core",
-                ),
-                canonical_name: "core",
-            },
-        ),
-        cfg_options: CfgOptions(
-            [
-                "debug_assertions",
-                "miri",
-                "true",
-            ],
-        ),
-        potential_cfg_options: None,
-        env: Env {
-            entries: {},
-        },
-        dependencies: [],
-        origin: Lang(
-            Core,
-        ),
-        is_proc_macro: false,
-        proc_macro_cwd: None,
-    },
-    2: CrateData {
-        root_file_id: FileId(
-            3,
-        ),
-        edition: Edition2021,
-        version: None,
-        display_name: Some(
-            CrateDisplayName {
-                crate_name: CrateName(
-                    "panic_abort",
-                ),
-                canonical_name: "panic_abort",
-            },
-        ),
-        cfg_options: CfgOptions(
-            [
-                "debug_assertions",
-                "miri",
-                "true",
-            ],
-        ),
-        potential_cfg_options: None,
-        env: Env {
-            entries: {},
-        },
-        dependencies: [],
-        origin: Lang(
-            Other,
-        ),
-        is_proc_macro: false,
-        proc_macro_cwd: None,
-    },
-    3: CrateData {
-        root_file_id: FileId(
-            4,
-        ),
-        edition: Edition2021,
-        version: None,
-        display_name: Some(
-            CrateDisplayName {
-                crate_name: CrateName(
-                    "panic_unwind",
-                ),
-                canonical_name: "panic_unwind",
-            },
-        ),
-        cfg_options: CfgOptions(
-            [
-                "debug_assertions",
-                "miri",
-                "true",
-            ],
-        ),
-        potential_cfg_options: None,
-        env: Env {
-            entries: {},
-        },
-        dependencies: [],
-        origin: Lang(
-            Other,
-        ),
-        is_proc_macro: false,
-        proc_macro_cwd: None,
-    },
-    4: CrateData {
-        root_file_id: FileId(
-            5,
-        ),
-        edition: Edition2021,
-        version: None,
-        display_name: Some(
-            CrateDisplayName {
-                crate_name: CrateName(
-                    "proc_macro",
-                ),
-                canonical_name: "proc_macro",
-            },
-        ),
-        cfg_options: CfgOptions(
-            [
-                "debug_assertions",
-                "miri",
-                "true",
-            ],
-        ),
-        potential_cfg_options: None,
-        env: Env {
-            entries: {},
-        },
-        dependencies: [
-            Dependency {
-                crate_id: Idx::<CrateData>(6),
-                name: CrateName(
-                    "std",
-                ),
-                prelude: true,
-                sysroot: false,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(1),
-                name: CrateName(
-                    "core",
-                ),
-                prelude: true,
-                sysroot: false,
-            },
-        ],
-        origin: Lang(
-            ProcMacro,
-        ),
-        is_proc_macro: false,
-        proc_macro_cwd: None,
-    },
-    5: CrateData {
-        root_file_id: FileId(
-            6,
-        ),
-        edition: Edition2021,
-        version: None,
-        display_name: Some(
-            CrateDisplayName {
-                crate_name: CrateName(
-                    "profiler_builtins",
-                ),
-                canonical_name: "profiler_builtins",
-            },
-        ),
-        cfg_options: CfgOptions(
-            [
-                "debug_assertions",
-                "miri",
-                "true",
-            ],
-        ),
-        potential_cfg_options: None,
-        env: Env {
-            entries: {},
-        },
-        dependencies: [],
-        origin: Lang(
-            Other,
-        ),
-        is_proc_macro: false,
-        proc_macro_cwd: None,
-    },
-    6: CrateData {
-        root_file_id: FileId(
-            7,
-        ),
-        edition: Edition2021,
-        version: None,
-        display_name: Some(
-            CrateDisplayName {
-                crate_name: CrateName(
-                    "std",
-                ),
-                canonical_name: "std",
-            },
-        ),
-        cfg_options: CfgOptions(
-            [
-                "debug_assertions",
-                "miri",
-                "true",
-            ],
-        ),
-        potential_cfg_options: None,
-        env: Env {
-            entries: {},
-        },
-        dependencies: [
-            Dependency {
-                crate_id: Idx::<CrateData>(0),
-                name: CrateName(
-                    "alloc",
-                ),
-                prelude: true,
-                sysroot: false,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(3),
-                name: CrateName(
-                    "panic_unwind",
-                ),
-                prelude: true,
-                sysroot: false,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(2),
-                name: CrateName(
-                    "panic_abort",
-                ),
-                prelude: true,
-                sysroot: false,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(1),
-                name: CrateName(
-                    "core",
-                ),
-                prelude: true,
-                sysroot: false,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(5),
-                name: CrateName(
-                    "profiler_builtins",
-                ),
-                prelude: true,
-                sysroot: false,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(9),
-                name: CrateName(
-                    "unwind",
-                ),
-                prelude: true,
-                sysroot: false,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(7),
-                name: CrateName(
-                    "std_detect",
-                ),
-                prelude: true,
-                sysroot: false,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(8),
-                name: CrateName(
-                    "test",
-                ),
-                prelude: true,
-                sysroot: false,
-            },
-        ],
-        origin: Lang(
-            Std,
-        ),
-        is_proc_macro: false,
-        proc_macro_cwd: None,
-    },
-    7: CrateData {
-        root_file_id: FileId(
-            8,
-        ),
-        edition: Edition2021,
-        version: None,
-        display_name: Some(
-            CrateDisplayName {
-                crate_name: CrateName(
-                    "std_detect",
-                ),
-                canonical_name: "std_detect",
-            },
-        ),
-        cfg_options: CfgOptions(
-            [
-                "debug_assertions",
-                "miri",
-                "true",
-            ],
-        ),
-        potential_cfg_options: None,
-        env: Env {
-            entries: {},
-        },
-        dependencies: [],
-        origin: Lang(
-            Other,
-        ),
-        is_proc_macro: false,
-        proc_macro_cwd: None,
-    },
-    8: CrateData {
-        root_file_id: FileId(
-            9,
-        ),
-        edition: Edition2021,
-        version: None,
-        display_name: Some(
-            CrateDisplayName {
-                crate_name: CrateName(
-                    "test",
-                ),
-                canonical_name: "test",
-            },
-        ),
-        cfg_options: CfgOptions(
-            [
-                "debug_assertions",
-                "miri",
-                "true",
-            ],
-        ),
-        potential_cfg_options: None,
-        env: Env {
-            entries: {},
-        },
-        dependencies: [],
-        origin: Lang(
-            Test,
-        ),
-        is_proc_macro: false,
-        proc_macro_cwd: None,
-    },
-    9: CrateData {
-        root_file_id: FileId(
-            10,
-        ),
-        edition: Edition2021,
-        version: None,
-        display_name: Some(
-            CrateDisplayName {
-                crate_name: CrateName(
-                    "unwind",
-                ),
-                canonical_name: "unwind",
-            },
-        ),
-        cfg_options: CfgOptions(
-            [
-                "debug_assertions",
-                "miri",
-                "true",
-            ],
-        ),
-        potential_cfg_options: None,
-        env: Env {
-            entries: {},
-        },
-        dependencies: [],
-        origin: Lang(
-            Other,
-        ),
-        is_proc_macro: false,
-        proc_macro_cwd: None,
-    },
-    10: CrateData {
-        root_file_id: FileId(
-            11,
-        ),
         edition: Edition2018,
         version: None,
         display_name: Some(
@@ -435,48 +24,7 @@
         env: Env {
             entries: {},
         },
-        dependencies: [
-            Dependency {
-                crate_id: Idx::<CrateData>(1),
-                name: CrateName(
-                    "core",
-                ),
-                prelude: true,
-                sysroot: true,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(0),
-                name: CrateName(
-                    "alloc",
-                ),
-                prelude: false,
-                sysroot: true,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(6),
-                name: CrateName(
-                    "std",
-                ),
-                prelude: true,
-                sysroot: true,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(8),
-                name: CrateName(
-                    "test",
-                ),
-                prelude: false,
-                sysroot: true,
-            },
-            Dependency {
-                crate_id: Idx::<CrateData>(4),
-                name: CrateName(
-                    "proc_macro",
-                ),
-                prelude: false,
-                sysroot: true,
-            },
-        ],
+        dependencies: [],
         origin: Local {
             repo: None,
             name: Some(
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
index b8ce2b7430b..6c81c238fd3 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
@@ -13,7 +13,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [[bin]]
 name = "rust-analyzer"
@@ -94,7 +93,7 @@ syntax-bridge.workspace = true
 
 [features]
 jemalloc = ["jemallocator", "profile/jemalloc"]
-force-always-assert = ["always-assert/force"]
+force-always-assert = ["stdx/force-always-assert"]
 sysroot-abi = []
 in-rust-tree = [
   "sysroot-abi",
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 1dce0bea1a9..713e28c87cb 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -128,6 +128,8 @@ config_data! {
         /// Whether to show keyword hover popups. Only applies when
         /// `#rust-analyzer.hover.documentation.enable#` is set.
         hover_documentation_keywords_enable: bool  = true,
+        /// Whether to show drop glue information on hover.
+        hover_dropGlue_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.
@@ -1631,6 +1633,7 @@ impl Config {
                 Some(MaxSubstitutionLength::Limit(limit)) => ide::SubstTyLen::LimitTo(*limit),
                 None => ide::SubstTyLen::Unlimited,
             },
+            show_drop_glue: *self.hover_dropGlue_enable(),
         }
     }
 
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 1b144d90732..b91a5dbd416 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
@@ -941,9 +941,7 @@ pub(crate) fn handle_runnables(
 
         let update_test = runnable.update_test;
         if let Some(mut runnable) = to_proto::runnable(&snap, runnable)? {
-            if let Some(runnable) =
-                to_proto::make_update_runnable(&runnable, &update_test.label(), &update_test.env())
-            {
+            if let Some(runnable) = to_proto::make_update_runnable(&runnable, update_test) {
                 res.push(runnable);
             }
 
@@ -2158,7 +2156,7 @@ fn runnable_action_links(
 
     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()) {
+        if let Some(r) = to_proto::make_update_runnable(&r, update_test) {
             let update_command = to_proto::command::run_single(&r, label.unwrap().as_str());
             group.commands.push(to_command_link(update_command, r.label.clone()));
         }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs
index b1136dbbdac..9c6b69d7312 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/capabilities.rs
@@ -165,7 +165,7 @@ pub fn server_capabilities(config: &Config) -> ServerCapabilities {
         })),
         diagnostic_provider: Some(lsp_types::DiagnosticServerCapabilities::Options(
             lsp_types::DiagnosticOptions {
-                identifier: None,
+                identifier: Some("rust-analyzer".to_owned()),
                 inter_file_dependencies: true,
                 // FIXME
                 workspace_diagnostics: false,
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 bff53cf98b7..446549c9070 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
@@ -14,13 +14,13 @@ use ide::{
     InlayFieldsToResolve, InlayHint, InlayHintLabel, InlayHintLabelPart, InlayKind, LazyProperty,
     Markup, NavigationTarget, ReferenceCategory, RenameError, Runnable, Severity, SignatureHelp,
     SnippetEdit, SourceChange, StructureNodeKind, SymbolKind, TextEdit, TextRange, TextSize,
+    UpdateTest,
 };
 use ide_db::{assists, rust_doc::format_docs, FxHasher};
 use itertools::Itertools;
 use paths::{Utf8Component, Utf8Prefix};
 use semver::VersionReq;
 use serde_json::to_value;
-use syntax::SmolStr;
 use vfs::AbsPath;
 
 use crate::{
@@ -1623,8 +1623,7 @@ pub(crate) fn code_lens(
                     }
                     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) {
+                        if let Some(r) = make_update_runnable(&r, update_test) {
                             let command = command::run_single(&r, label.unwrap().as_str());
                             acc.push(lsp_types::CodeLens {
                                 range: annotation_range,
@@ -1871,22 +1870,22 @@ pub(crate) mod command {
 
 pub(crate) fn make_update_runnable(
     runnable: &lsp_ext::Runnable,
-    label: &Option<SmolStr>,
-    env: &[(&str, &str)],
+    update_test: UpdateTest,
 ) -> Option<lsp_ext::Runnable> {
-    if !matches!(runnable.args, lsp_ext::RunnableArgs::Cargo(_)) {
-        return None;
-    }
-    let label = label.as_ref()?;
+    let label = update_test.label()?;
 
     let mut runnable = runnable.clone();
     runnable.label = format!("{} + {}", runnable.label, label);
 
     let lsp_ext::RunnableArgs::Cargo(r) = &mut runnable.args else {
-        unreachable!();
+        return None;
     };
 
-    r.environment.extend(env.iter().map(|(k, v)| (k.to_string(), v.to_string())));
+    r.environment.extend(update_test.env().iter().map(|(k, v)| (k.to_string(), v.to_string())));
+
+    if update_test.insta {
+        r.cargo_args.insert(0, "insta".to_owned());
+    }
 
     Some(runnable)
 }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/op_queue.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/op_queue.rs
index 123f20605ab..709d99bda75 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/op_queue.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/op_queue.rs
@@ -6,7 +6,7 @@ pub(crate) type Cause = String;
 /// A single-item queue that allows callers to request an operation to
 /// be performed later.
 ///
-/// ```
+/// ```ignore
 /// let queue = OpQueue::default();
 ///
 /// // Request work to be done.
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/config.rs
index 02ae4186ab6..4f208b6c5dd 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/config.rs
@@ -31,7 +31,7 @@ pub struct Config<T> {
     /// that specify level.
     pub chalk_filter: Option<String>,
     /// Filtering syntax, set in a shell:
-    /// ```
+    /// ```text
     /// env RA_PROFILE=*             // dump everything
     /// env RA_PROFILE=foo|bar|baz   // enabled only selected entries
     /// env RA_PROFILE=*@3>10        // dump everything, up to depth 3, if it takes more than 10
@@ -39,7 +39,7 @@ pub struct Config<T> {
     pub profile_filter: Option<String>,
 
     /// Filtering syntax, set in a shell:
-    /// ```
+    /// ```text
     /// env RA_PROFILE_JSON=foo|bar|baz
     /// ```
     pub json_profile_filter: Option<String>,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/hprof.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/hprof.rs
index d466acef011..5b18762bb97 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/hprof.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/hprof.rs
@@ -6,7 +6,8 @@
 //!
 //! Usage:
 //!
-//! ```rust
+//! ```ignore
+//! # use tracing_subscriber::Registry;
 //! let layer = hprof::SpanTree::default();
 //! Registry::default().with(layer).init();
 //! ```
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/json.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/json.rs
index 9e35990a5bc..f5394d023a1 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/json.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/json.rs
@@ -2,7 +2,8 @@
 //!
 //! Usage:
 //!
-//! ```rust
+//! ```ignore
+//! # use tracing_subscriber::Registry;
 //! let layer = json::TimingLayer::new(std::io::stderr);
 //! Registry::default().with(layer).init();
 //! ```
diff --git a/src/tools/rust-analyzer/crates/stdx/Cargo.toml b/src/tools/rust-analyzer/crates/stdx/Cargo.toml
index 1ebb48c577a..3727d0c9562 100644
--- a/src/tools/rust-analyzer/crates/stdx/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/stdx/Cargo.toml
@@ -10,15 +10,14 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 backtrace = { version = "0.3.67", optional = true }
-always-assert = { version = "0.2.0", features = ["tracing"] }
 jod-thread = "0.1.2"
 libc.workspace = true
 crossbeam-channel.workspace = true
 itertools.workspace = true
+tracing.workspace = true
 # Think twice before adding anything here
 
 [target.'cfg(windows)'.dependencies]
@@ -28,6 +27,7 @@ windows-sys = { version = "0.59", features = ["Win32_Foundation"] }
 [features]
 # Uncomment to enable for the whole crate graph
 # default = [ "backtrace" ]
+force-always-assert = []
 
 [lints]
 workspace = true
diff --git a/src/tools/rust-analyzer/crates/stdx/src/anymap.rs b/src/tools/rust-analyzer/crates/stdx/src/anymap.rs
index 91fab8e9238..faf2e6c7178 100644
--- a/src/tools/rust-analyzer/crates/stdx/src/anymap.rs
+++ b/src/tools/rust-analyzer/crates/stdx/src/anymap.rs
@@ -83,7 +83,8 @@ pub type RawMap<A> = hash_map::HashMap<TypeId, Box<A>, BuildHasherDefault<TypeId
 /// (Here using the [`AnyMap`] convenience alias; the first line could use
 /// <code>[anymap::Map][Map]::&lt;[core::any::Any]&gt;::new()</code> instead if desired.)
 ///
-/// ```rust
+/// ```
+/// # use stdx::anymap;
 #[doc = "let mut data = anymap::AnyMap::new();"]
 /// assert_eq!(data.get(), None::<&i32>);
 /// ```
diff --git a/src/tools/rust-analyzer/crates/stdx/src/assert.rs b/src/tools/rust-analyzer/crates/stdx/src/assert.rs
new file mode 100644
index 00000000000..91c279798c2
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/stdx/src/assert.rs
@@ -0,0 +1,115 @@
+// Vendored from https://github.com/matklad/always-assert/commit/4cf564eea6fcf18b30c3c3483a611004dc03afbb
+//! Recoverable assertions, inspired by [the use of `assert()` in
+//! SQLite](https://www.sqlite.org/assert.html).
+//!
+//! `never!` and `always!` return the actual value of the condition if
+//! `debug_assertions` are disabled.
+//!
+//! Use them when terminating on assertion failure is worse than continuing.
+//!
+//! One example would be a critical application like a database:
+//!
+//! ```ignore
+//! use stdx::never;
+//!
+//! fn apply_transaction(&mut self, tx: Transaction) -> Result<(), TransactionAborted> {
+//!     let delta = self.compute_delta(&tx);
+//!
+//!     if never!(!self.check_internal_invariant(&delta)) {
+//!         // Ok, something in this transaction messed up our internal state.
+//!         // This really shouldn't be happening, and this signifies a bug.
+//!         // Luckily, we can recover by just rejecting the transaction.
+//!         return abort_transaction(tx);
+//!     }
+//!     self.commit(delta);
+//!     Ok(())
+//! }
+//! ```
+//!
+//! Another example is assertions about non-critical functionality in usual apps
+//!
+//! ```ignore
+//! use stdx::never;
+//!
+//! let english_message = "super app installed!"
+//! let mut local_message = localize(english_message);
+//! if never!(local_message.is_empty(), "missing localization for {}", english_message) {
+//!     // We localized all the messages but this one slipper through the cracks?
+//!     // Better to show the english one then than to fail outright;
+//!     local_message = english_message;
+//! }
+//! println!("{}", local_message);
+//! ```
+
+/// Asserts that the condition is always true and returns its actual value.
+///
+/// If the condition is true does nothing and and evaluates to true.
+///
+/// If the condition is false:
+/// * panics if `force` feature or `debug_assertions` are enabled,
+/// * logs an error if the `tracing` feature is enabled,
+/// * evaluates to false.
+///
+/// Accepts `format!` style arguments.
+#[macro_export]
+macro_rules! always {
+    ($cond:expr) => {
+        $crate::always!($cond, "assertion failed: {}", stringify!($cond))
+    };
+
+    ($cond:expr, $fmt:literal $($arg:tt)*) => {{
+        let cond = $cond;
+        if cfg!(debug_assertions) || $crate::assert::__FORCE {
+            assert!(cond, $fmt $($arg)*);
+        }
+        if !cond {
+            $crate::assert::__tracing_error!($fmt $($arg)*);
+        }
+        cond
+    }};
+}
+
+/// Asserts that the condition is never true and returns its actual value.
+///
+/// If the condition is false does nothing and and evaluates to false.
+///
+/// If the condition is true:
+/// * panics if `force` feature or `debug_assertions` are enabled,
+/// * logs an error if the `tracing` feature is enabled,
+/// * evaluates to true.
+///
+/// Accepts `format!` style arguments.
+///
+/// Empty condition is equivalent to false:
+///
+/// ```ignore
+/// never!("oups") ~= unreachable!("oups")
+/// ```
+#[macro_export]
+macro_rules! never {
+    (true $($tt:tt)*) => { $crate::never!((true) $($tt)*) };
+    (false $($tt:tt)*) => { $crate::never!((false) $($tt)*) };
+    () => { $crate::never!("assertion failed: entered unreachable code") };
+    ($fmt:literal $(, $($arg:tt)*)?) => {{
+        if cfg!(debug_assertions) || $crate::assert::__FORCE {
+            unreachable!($fmt $(, $($arg)*)?);
+        }
+        $crate::assert::__tracing_error!($fmt $(, $($arg)*)?);
+    }};
+
+    ($cond:expr) => {{
+        let cond = !$crate::always!(!$cond);
+        cond
+    }};
+
+    ($cond:expr, $fmt:literal $($arg:tt)*) => {{
+        let cond = !$crate::always!(!$cond, $fmt $($arg)*);
+        cond
+    }};
+}
+
+#[doc(hidden)]
+pub use tracing::error as __tracing_error;
+
+#[doc(hidden)]
+pub const __FORCE: bool = cfg!(feature = "force-always-assert");
diff --git a/src/tools/rust-analyzer/crates/stdx/src/lib.rs b/src/tools/rust-analyzer/crates/stdx/src/lib.rs
index 04c2153abf4..8313e1871f1 100644
--- a/src/tools/rust-analyzer/crates/stdx/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/stdx/src/lib.rs
@@ -4,8 +4,10 @@ use std::io as sio;
 use std::process::Command;
 use std::{cmp::Ordering, ops, time::Instant};
 
-pub mod anymap;
 mod macros;
+
+pub mod anymap;
+pub mod assert;
 pub mod non_empty_vec;
 pub mod panic_context;
 pub mod process;
@@ -13,7 +15,6 @@ pub mod rand;
 pub mod thin_vec;
 pub mod thread;
 
-pub use always_assert::{always, never};
 pub use itertools;
 
 #[inline(always)]
diff --git a/src/tools/rust-analyzer/crates/stdx/src/macros.rs b/src/tools/rust-analyzer/crates/stdx/src/macros.rs
index 85d9008fe12..880e2da70fc 100644
--- a/src/tools/rust-analyzer/crates/stdx/src/macros.rs
+++ b/src/tools/rust-analyzer/crates/stdx/src/macros.rs
@@ -34,7 +34,7 @@ macro_rules! format_to_acc {
 ///
 /// # Example
 ///
-/// ```rust
+/// ```ignore
 /// impl_from!(Struct, Union, Enum for Adt);
 /// ```
 #[macro_export]
diff --git a/src/tools/rust-analyzer/crates/syntax-bridge/Cargo.toml b/src/tools/rust-analyzer/crates/syntax-bridge/Cargo.toml
index f9a9f40541d..3e663422a04 100644
--- a/src/tools/rust-analyzer/crates/syntax-bridge/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/syntax-bridge/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 rustc-hash.workspace = true
diff --git a/src/tools/rust-analyzer/crates/syntax/Cargo.toml b/src/tools/rust-analyzer/crates/syntax/Cargo.toml
index 51eaea54346..3fe6e01dc3c 100644
--- a/src/tools/rust-analyzer/crates/syntax/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/syntax/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 cov-mark = "2.0.0-pre.1"
diff --git a/src/tools/rust-analyzer/crates/syntax/rust.ungram b/src/tools/rust-analyzer/crates/syntax/rust.ungram
index bbb8413cbc0..88d7beb897e 100644
--- a/src/tools/rust-analyzer/crates/syntax/rust.ungram
+++ b/src/tools/rust-analyzer/crates/syntax/rust.ungram
@@ -438,9 +438,9 @@ MacroExpr =
 Literal =
   Attr* value:(
     '@int_number' | '@float_number'
-  | '@string' | '@raw_string'
-  | '@byte_string' | '@raw_byte_string'
-  | '@c_string' | '@raw_c_string'
+  | '@string'
+  | '@byte_string'
+  | '@c_string'
   | '@char' | '@byte'
   | 'true' | 'false'
   )
diff --git a/src/tools/rust-analyzer/crates/syntax/src/algo.rs b/src/tools/rust-analyzer/crates/syntax/src/algo.rs
index 2acb2158318..a8a83893946 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/algo.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/algo.rs
@@ -3,8 +3,8 @@
 use itertools::Itertools;
 
 use crate::{
-    AstNode, Direction, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, TextRange,
-    TextSize,
+    syntax_editor::Element, AstNode, Direction, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode,
+    SyntaxToken, TextRange, TextSize,
 };
 
 /// Returns ancestors of the node at the offset, sorted by length. This should
@@ -25,7 +25,7 @@ pub fn ancestors_at_offset(
 /// imprecise: if the cursor is strictly between two nodes of the desired type,
 /// as in
 ///
-/// ```no_run
+/// ```ignore
 /// struct Foo {}|struct Bar;
 /// ```
 ///
@@ -89,6 +89,26 @@ pub fn least_common_ancestor(u: &SyntaxNode, v: &SyntaxNode) -> Option<SyntaxNod
     Some(res)
 }
 
+pub fn least_common_ancestor_element(u: impl Element, v: impl Element) -> Option<SyntaxNode> {
+    let u = u.syntax_element();
+    let v = v.syntax_element();
+    if u == v {
+        return match u {
+            NodeOrToken::Node(node) => Some(node),
+            NodeOrToken::Token(token) => token.parent(),
+        };
+    }
+
+    let u_depth = u.ancestors().count();
+    let v_depth = v.ancestors().count();
+    let keep = u_depth.min(v_depth);
+
+    let u_candidates = u.ancestors().skip(u_depth - keep);
+    let v_candidates = v.ancestors().skip(v_depth - keep);
+    let (res, _) = u_candidates.zip(v_candidates).find(|(x, y)| x == y)?;
+    Some(res)
+}
+
 pub fn neighbor<T: AstNode>(me: &T, direction: Direction) -> Option<T> {
     me.syntax().siblings(direction).skip(1).find_map(T::cast)
 }
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/edit.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/edit.rs
index 579f3ba8b4f..052d018e5c9 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/edit.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/edit.rs
@@ -72,9 +72,9 @@ impl IndentLevel {
     }
 
     /// XXX: this intentionally doesn't change the indent of the very first token.
-    /// Ie, in something like
+    /// For example, in something like:
     /// ```
-    /// fn foo() {
+    /// fn foo() -> i32 {
     ///    92
     /// }
     /// ```
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 9dc2d832530..231c21c38f8 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
@@ -784,7 +784,7 @@ pub fn record_pat_field_shorthand(name_ref: ast::NameRef) -> ast::RecordPatField
     ast_from_text(&format!("fn f(S {{ {name_ref} }}: ()))"))
 }
 
-/// Returns a `BindPat` if the path has just one segment, a `PathPat` otherwise.
+/// Returns a `IdentPat` if the path has just one segment, a `PathPat` otherwise.
 pub fn path_pat(path: ast::Path) -> ast::Pat {
     return from_text(&path.to_string());
     fn from_text(text: &str) -> ast::Pat {
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/prec.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/prec.rs
index 5d33f132ac1..0c4da762992 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/prec.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/prec.rs
@@ -7,7 +7,7 @@ use crate::{
 
 #[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
 pub enum ExprPrecedence {
-    // return, break, yield, closures
+    // return val, break val, yield val, closures
     Jump,
     // = += -= *= /= %= &= |= ^= <<= >>=
     Assign,
@@ -35,10 +35,27 @@ pub enum ExprPrecedence {
     Cast,
     // unary - * ! & &mut
     Prefix,
-    // paths, loops, function calls, array indexing, field expressions, method calls
+    // function calls, array indexing, field expressions, method calls
+    Postfix,
+    // paths, loops,
     Unambiguous,
 }
 
+impl ExprPrecedence {
+    pub fn needs_parentheses_in(self, other: ExprPrecedence) -> bool {
+        match other {
+            ExprPrecedence::Unambiguous => false,
+            // postfix ops have higher precedence than any other operator, so we need to wrap
+            // any inner expression that is below
+            ExprPrecedence::Postfix => self < ExprPrecedence::Postfix,
+            // We need to wrap all binary like things, thats everything below prefix except for
+            // jumps (as those are prefix operations as well)
+            ExprPrecedence::Prefix => ExprPrecedence::Jump < self && self < ExprPrecedence::Prefix,
+            parent => self <= parent,
+        }
+    }
+}
+
 #[derive(PartialEq, Debug)]
 pub enum Fixity {
     /// The operator is left-associative
@@ -56,11 +73,18 @@ pub fn precedence(expr: &ast::Expr) -> ExprPrecedence {
             Some(_) => ExprPrecedence::Unambiguous,
         },
 
+        Expr::BreakExpr(e) if e.expr().is_some() => ExprPrecedence::Jump,
+        Expr::BecomeExpr(e) if e.expr().is_some() => ExprPrecedence::Jump,
+        Expr::ReturnExpr(e) if e.expr().is_some() => ExprPrecedence::Jump,
+        Expr::YeetExpr(e) if e.expr().is_some() => ExprPrecedence::Jump,
+        Expr::YieldExpr(e) if e.expr().is_some() => ExprPrecedence::Jump,
+
         Expr::BreakExpr(_)
-        | Expr::ContinueExpr(_)
+        | Expr::BecomeExpr(_)
         | Expr::ReturnExpr(_)
         | Expr::YeetExpr(_)
-        | Expr::YieldExpr(_) => ExprPrecedence::Jump,
+        | Expr::YieldExpr(_)
+        | Expr::ContinueExpr(_) => ExprPrecedence::Unambiguous,
 
         Expr::RangeExpr(..) => ExprPrecedence::Range,
 
@@ -89,27 +113,27 @@ pub fn precedence(expr: &ast::Expr) -> ExprPrecedence {
 
         Expr::LetExpr(_) | Expr::PrefixExpr(_) | Expr::RefExpr(_) => ExprPrecedence::Prefix,
 
+        Expr::AwaitExpr(_)
+        | Expr::CallExpr(_)
+        | Expr::FieldExpr(_)
+        | Expr::IndexExpr(_)
+        | Expr::MethodCallExpr(_)
+        | Expr::TryExpr(_) => ExprPrecedence::Postfix,
+
         Expr::ArrayExpr(_)
         | Expr::AsmExpr(_)
-        | Expr::AwaitExpr(_)
-        | Expr::BecomeExpr(_)
         | Expr::BlockExpr(_)
-        | Expr::CallExpr(_)
-        | Expr::FieldExpr(_)
         | Expr::ForExpr(_)
         | Expr::FormatArgsExpr(_)
         | Expr::IfExpr(_)
-        | Expr::IndexExpr(_)
         | Expr::Literal(_)
         | Expr::LoopExpr(_)
         | Expr::MacroExpr(_)
         | Expr::MatchExpr(_)
-        | Expr::MethodCallExpr(_)
         | Expr::OffsetOfExpr(_)
         | Expr::ParenExpr(_)
         | Expr::PathExpr(_)
         | Expr::RecordExpr(_)
-        | Expr::TryExpr(_)
         | Expr::TupleExpr(_)
         | Expr::UnderscoreExpr(_)
         | Expr::WhileExpr(_) => ExprPrecedence::Unambiguous,
@@ -128,7 +152,7 @@ impl Expr {
     //   - https://github.com/rust-lang/rust/blob/b6852428a8ea9728369b64b9964cad8e258403d3/compiler/rustc_ast/src/util/parser.rs#L296
 
     /// Returns `true` if `self` would need to be wrapped in parentheses given that its parent is `parent`.
-    pub fn needs_parens_in(&self, parent: SyntaxNode) -> bool {
+    pub fn needs_parens_in(&self, parent: &SyntaxNode) -> bool {
         match_ast! {
             match parent {
                 ast::Expr(e) => self.needs_parens_in_expr(&e),
@@ -384,6 +408,7 @@ impl Expr {
             BreakExpr(e) => e.expr().is_none(),
             ContinueExpr(_) => true,
             YieldExpr(e) => e.expr().is_none(),
+            BecomeExpr(e) => e.expr().is_none(),
             _ => false,
         }
     }
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory.rs
index 73bbe49105d..1c517ac2c77 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/syntax_factory.rs
@@ -33,6 +33,11 @@ impl SyntaxFactory {
         self.mappings.unwrap_or_default().into_inner()
     }
 
+    /// Take all of the tracked syntax mappings, leaving `SyntaxMapping::default()` in its place, if any.
+    pub fn take(&self) -> SyntaxMapping {
+        self.mappings.as_ref().map(|mappings| mappings.take()).unwrap_or_default()
+    }
+
     fn mappings(&self) -> Option<RefMut<'_, SyntaxMapping>> {
         self.mappings.as_ref().map(|it| it.borrow_mut())
     }
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 572622db544..85393ca5b4c 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
@@ -129,7 +129,7 @@ impl SyntaxFactory {
 
         if let Some(mut mapping) = self.mappings() {
             let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
-            builder.map_children(input.into_iter(), ast.segments().map(|it| it.syntax().clone()));
+            builder.map_children(input, ast.segments().map(|it| it.syntax().clone()));
             builder.finish(&mut mapping);
         }
 
@@ -156,6 +156,32 @@ impl SyntaxFactory {
         make::literal_pat(text).clone_for_update()
     }
 
+    pub fn slice_pat(&self, pats: impl IntoIterator<Item = ast::Pat>) -> ast::SlicePat {
+        let (pats, input) = iterator_input(pats);
+        let ast = make::slice_pat(pats).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder.map_children(input, ast.pats().map(|it| it.syntax().clone()));
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
+    pub fn tuple_pat(&self, pats: impl IntoIterator<Item = ast::Pat>) -> ast::TuplePat {
+        let (pats, input) = iterator_input(pats);
+        let ast = make::tuple_pat(pats).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder.map_children(input, ast.fields().map(|it| it.syntax().clone()));
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
     pub fn tuple_struct_pat(
         &self,
         path: ast::Path,
@@ -167,13 +193,103 @@ impl SyntaxFactory {
         if let Some(mut mapping) = self.mappings() {
             let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
             builder.map_node(path.syntax().clone(), ast.path().unwrap().syntax().clone());
-            builder.map_children(input.into_iter(), ast.fields().map(|it| it.syntax().clone()));
+            builder.map_children(input, ast.fields().map(|it| it.syntax().clone()));
             builder.finish(&mut mapping);
         }
 
         ast
     }
 
+    pub fn record_pat_with_fields(
+        &self,
+        path: ast::Path,
+        fields: ast::RecordPatFieldList,
+    ) -> ast::RecordPat {
+        let ast = make::record_pat_with_fields(path.clone(), fields.clone()).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder.map_node(path.syntax().clone(), ast.path().unwrap().syntax().clone());
+            builder.map_node(
+                fields.syntax().clone(),
+                ast.record_pat_field_list().unwrap().syntax().clone(),
+            );
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
+    pub fn record_pat_field_list(
+        &self,
+        fields: impl IntoIterator<Item = ast::RecordPatField>,
+        rest_pat: Option<ast::RestPat>,
+    ) -> ast::RecordPatFieldList {
+        let (fields, input) = iterator_input(fields);
+        let ast = make::record_pat_field_list(fields, rest_pat.clone()).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder.map_children(input, ast.fields().map(|it| it.syntax().clone()));
+            if let Some(rest_pat) = rest_pat {
+                builder
+                    .map_node(rest_pat.syntax().clone(), ast.rest_pat().unwrap().syntax().clone());
+            }
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
+    pub fn record_pat_field(self, name_ref: ast::NameRef, pat: ast::Pat) -> ast::RecordPatField {
+        let ast = make::record_pat_field(name_ref.clone(), pat.clone()).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder.map_node(name_ref.syntax().clone(), ast.name_ref().unwrap().syntax().clone());
+            builder.map_node(pat.syntax().clone(), ast.pat().unwrap().syntax().clone());
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
+    pub fn record_pat_field_shorthand(&self, name_ref: ast::NameRef) -> ast::RecordPatField {
+        let ast = make::record_pat_field_shorthand(name_ref.clone()).clone_for_update();
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder.map_node(name_ref.syntax().clone(), ast.pat().unwrap().syntax().clone());
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
+    pub fn path_pat(&self, path: ast::Path) -> ast::Pat {
+        let ast = make::path_pat(path.clone()).clone_for_update();
+
+        match &ast {
+            ast::Pat::PathPat(ast) => {
+                if let Some(mut mapping) = self.mappings() {
+                    let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+                    builder.map_node(path.syntax().clone(), ast.path().unwrap().syntax().clone());
+                    builder.finish(&mut mapping)
+                }
+            }
+            ast::Pat::IdentPat(ast) => {
+                if let Some(mut mapping) = self.mappings() {
+                    let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+                    builder.map_node(path.syntax().clone(), ast.name().unwrap().syntax().clone());
+                    builder.finish(&mut mapping)
+                }
+            }
+            _ => unreachable!(),
+        }
+
+        ast
+    }
+
     pub fn block_expr(
         &self,
         statements: impl IntoIterator<Item = ast::Stmt>,
@@ -199,10 +315,7 @@ impl SyntaxFactory {
                 builder.map_node(last_stmt, ast_tail.syntax().clone());
             }
 
-            builder.map_children(
-                input.into_iter(),
-                stmt_list.statements().map(|it| it.syntax().clone()),
-            );
+            builder.map_children(input, stmt_list.statements().map(|it| it.syntax().clone()));
 
             builder.finish(&mut mapping);
         }
@@ -214,13 +327,28 @@ impl SyntaxFactory {
         make::expr_empty_block().clone_for_update()
     }
 
+    pub fn expr_paren(&self, expr: ast::Expr) -> ast::ParenExpr {
+        // FIXME: `make::expr_paren` should return a `ParenExpr`, not just an `Expr`
+        let ast::Expr::ParenExpr(ast) = make::expr_paren(expr.clone()).clone_for_update() else {
+            unreachable!()
+        };
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder.map_node(expr.syntax().clone(), ast.expr().unwrap().syntax().clone());
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
     pub fn expr_tuple(&self, fields: impl IntoIterator<Item = ast::Expr>) -> ast::TupleExpr {
         let (fields, input) = iterator_input(fields);
         let ast = make::expr_tuple(fields).clone_for_update();
 
         if let Some(mut mapping) = self.mappings() {
             let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
-            builder.map_children(input.into_iter(), ast.fields().map(|it| it.syntax().clone()));
+            builder.map_children(input, ast.fields().map(|it| it.syntax().clone()));
             builder.finish(&mut mapping);
         }
 
@@ -292,13 +420,38 @@ impl SyntaxFactory {
         ast
     }
 
+    pub fn expr_method_call(
+        &self,
+        receiver: ast::Expr,
+        method: ast::NameRef,
+        arg_list: ast::ArgList,
+    ) -> ast::MethodCallExpr {
+        // FIXME: `make::expr_method_call` should return a `MethodCallExpr`, not just an `Expr`
+        let ast::Expr::MethodCallExpr(ast) =
+            make::expr_method_call(receiver.clone(), method.clone(), arg_list.clone())
+                .clone_for_update()
+        else {
+            unreachable!()
+        };
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder.map_node(receiver.syntax().clone(), ast.receiver().unwrap().syntax().clone());
+            builder.map_node(method.syntax().clone(), ast.name_ref().unwrap().syntax().clone());
+            builder.map_node(arg_list.syntax().clone(), ast.arg_list().unwrap().syntax().clone());
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
     pub fn arg_list(&self, args: impl IntoIterator<Item = ast::Expr>) -> ast::ArgList {
         let (args, input) = iterator_input(args);
         let ast = make::arg_list(args).clone_for_update();
 
         if let Some(mut mapping) = self.mappings() {
             let mut builder = SyntaxMappingBuilder::new(ast.syntax.clone());
-            builder.map_children(input.into_iter(), ast.args().map(|it| it.syntax().clone()));
+            builder.map_children(input, ast.args().map(|it| it.syntax().clone()));
             builder.finish(&mut mapping);
         }
 
@@ -320,6 +473,31 @@ impl SyntaxFactory {
         ast.into()
     }
 
+    pub fn expr_closure(
+        &self,
+        pats: impl IntoIterator<Item = ast::Param>,
+        expr: ast::Expr,
+    ) -> ast::ClosureExpr {
+        let (args, input) = iterator_input(pats);
+        // FIXME: `make::expr_paren` should return a `ClosureExpr`, not just an `Expr`
+        let ast::Expr::ClosureExpr(ast) = make::expr_closure(args, expr.clone()).clone_for_update()
+        else {
+            unreachable!()
+        };
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax.clone());
+            builder.map_children(
+                input,
+                ast.param_list().unwrap().params().map(|param| param.syntax().clone()),
+            );
+            builder.map_node(expr.syntax().clone(), ast.body().unwrap().syntax().clone());
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
     pub fn expr_return(&self, expr: Option<ast::Expr>) -> ast::ReturnExpr {
         let ast::Expr::ReturnExpr(ast) = make::expr_return(expr.clone()).clone_for_update() else {
             unreachable!()
@@ -448,7 +626,7 @@ impl SyntaxFactory {
 
         if let Some(mut mapping) = self.mappings() {
             let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
-            builder.map_children(input.into_iter(), ast.arms().map(|it| it.syntax().clone()));
+            builder.map_children(input, ast.arms().map(|it| it.syntax().clone()));
             builder.finish(&mut mapping);
         }
 
@@ -571,6 +749,19 @@ impl SyntaxFactory {
         ast
     }
 
+    pub fn param(&self, pat: ast::Pat, ty: ast::Type) -> ast::Param {
+        let ast = make::param(pat.clone(), ty.clone());
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+            builder.map_node(pat.syntax().clone(), ast.pat().unwrap().syntax().clone());
+            builder.map_node(ty.syntax().clone(), ast.ty().unwrap().syntax().clone());
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
     pub fn generic_arg_list(
         &self,
         generic_args: impl IntoIterator<Item = ast::GenericArg>,
@@ -585,10 +776,7 @@ impl SyntaxFactory {
 
         if let Some(mut mapping) = self.mappings() {
             let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
-            builder.map_children(
-                input.into_iter(),
-                ast.generic_args().map(|arg| arg.syntax().clone()),
-            );
+            builder.map_children(input, ast.generic_args().map(|arg| arg.syntax().clone()));
             builder.finish(&mut mapping);
         }
 
@@ -605,7 +793,7 @@ impl SyntaxFactory {
         if let Some(mut mapping) = self.mappings() {
             let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
 
-            builder.map_children(input.into_iter(), ast.fields().map(|it| it.syntax().clone()));
+            builder.map_children(input, ast.fields().map(|it| it.syntax().clone()));
 
             builder.finish(&mut mapping);
         }
@@ -650,7 +838,7 @@ impl SyntaxFactory {
         if let Some(mut mapping) = self.mappings() {
             let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
 
-            builder.map_children(input.into_iter(), ast.fields().map(|it| it.syntax().clone()));
+            builder.map_children(input, ast.fields().map(|it| it.syntax().clone()));
 
             builder.finish(&mut mapping);
         }
@@ -745,7 +933,7 @@ impl SyntaxFactory {
         if let Some(mut mapping) = self.mappings() {
             let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
 
-            builder.map_children(input.into_iter(), ast.variants().map(|it| it.syntax().clone()));
+            builder.map_children(input, ast.variants().map(|it| it.syntax().clone()));
 
             builder.finish(&mut mapping);
         }
@@ -797,6 +985,69 @@ impl SyntaxFactory {
         ast
     }
 
+    pub fn fn_(
+        &self,
+        visibility: Option<ast::Visibility>,
+        fn_name: ast::Name,
+        type_params: Option<ast::GenericParamList>,
+        where_clause: Option<ast::WhereClause>,
+        params: ast::ParamList,
+        body: ast::BlockExpr,
+        ret_type: Option<ast::RetType>,
+        is_async: bool,
+        is_const: bool,
+        is_unsafe: bool,
+        is_gen: bool,
+    ) -> ast::Fn {
+        let ast = make::fn_(
+            visibility.clone(),
+            fn_name.clone(),
+            type_params.clone(),
+            where_clause.clone(),
+            params.clone(),
+            body.clone(),
+            ret_type.clone(),
+            is_async,
+            is_const,
+            is_unsafe,
+            is_gen,
+        );
+
+        if let Some(mut mapping) = self.mappings() {
+            let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+
+            if let Some(visibility) = visibility {
+                builder.map_node(
+                    visibility.syntax().clone(),
+                    ast.visibility().unwrap().syntax().clone(),
+                );
+            }
+            builder.map_node(fn_name.syntax().clone(), ast.name().unwrap().syntax().clone());
+            if let Some(type_params) = type_params {
+                builder.map_node(
+                    type_params.syntax().clone(),
+                    ast.generic_param_list().unwrap().syntax().clone(),
+                );
+            }
+            if let Some(where_clause) = where_clause {
+                builder.map_node(
+                    where_clause.syntax().clone(),
+                    ast.where_clause().unwrap().syntax().clone(),
+                );
+            }
+            builder.map_node(params.syntax().clone(), ast.param_list().unwrap().syntax().clone());
+            builder.map_node(body.syntax().clone(), ast.body().unwrap().syntax().clone());
+            if let Some(ret_type) = ret_type {
+                builder
+                    .map_node(ret_type.syntax().clone(), ast.ret_type().unwrap().syntax().clone());
+            }
+
+            builder.finish(&mut mapping);
+        }
+
+        ast
+    }
+
     pub fn token_tree(
         &self,
         delimiter: SyntaxKind,
@@ -809,10 +1060,7 @@ impl SyntaxFactory {
 
         if let Some(mut mapping) = self.mappings() {
             let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
-            builder.map_children(
-                input.into_iter(),
-                ast.token_trees_and_tokens().filter_map(only_nodes),
-            );
+            builder.map_children(input, ast.token_trees_and_tokens().filter_map(only_nodes));
             builder.finish(&mut mapping);
         }
 
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 7d5ca270435..df851ab5b25 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
@@ -269,7 +269,7 @@ impl ast::ByteString {
             }
             (Ok(c), true) => {
                 buf.reserve_exact(text.len());
-                buf.extend_from_slice(text[..prev_end].as_bytes());
+                buf.extend_from_slice(&text.as_bytes()[..prev_end]);
                 buf.push(c as u8);
             }
             (Err(e), _) => has_error = Some(e),
@@ -333,7 +333,7 @@ impl ast::CString {
             }
             (Ok(u), true) => {
                 buf.reserve_exact(text.len());
-                buf.extend(text[..prev_end].as_bytes());
+                buf.extend(&text.as_bytes()[..prev_end]);
                 extend_unit(&mut buf, u);
             }
             (Err(e), _) => has_error = Some(e),
diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs
index b82181ae13a..48c160b9a9a 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor.rs
@@ -5,6 +5,7 @@
 //! [`SyntaxEditor`]: https://github.com/dotnet/roslyn/blob/43b0b05cc4f492fd5de00f6f6717409091df8daa/src/Workspaces/Core/Portable/Editing/SyntaxEditor.cs
 
 use std::{
+    fmt,
     num::NonZeroU32,
     ops::RangeInclusive,
     sync::atomic::{AtomicU32, Ordering},
@@ -282,6 +283,64 @@ enum ChangeKind {
     Replace,
 }
 
+impl fmt::Display for Change {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Change::Insert(position, node_or_token) => {
+                let parent = position.parent();
+                let mut parent_str = parent.to_string();
+                let target_range = self.target_range().start() - parent.text_range().start();
+
+                parent_str.insert_str(
+                    target_range.into(),
+                    &format!("\x1b[42m{node_or_token}\x1b[0m\x1b[K"),
+                );
+                f.write_str(&parent_str)
+            }
+            Change::InsertAll(position, vec) => {
+                let parent = position.parent();
+                let mut parent_str = parent.to_string();
+                let target_range = self.target_range().start() - parent.text_range().start();
+                let insertion: String = vec.iter().map(|it| it.to_string()).collect();
+
+                parent_str
+                    .insert_str(target_range.into(), &format!("\x1b[42m{insertion}\x1b[0m\x1b[K"));
+                f.write_str(&parent_str)
+            }
+            Change::Replace(old, new) => {
+                if let Some(new) = new {
+                    write!(f, "\x1b[41m{old}\x1b[42m{new}\x1b[0m\x1b[K")
+                } else {
+                    write!(f, "\x1b[41m{old}\x1b[0m\x1b[K")
+                }
+            }
+            Change::ReplaceWithMany(old, vec) => {
+                let new: String = vec.iter().map(|it| it.to_string()).collect();
+                write!(f, "\x1b[41m{old}\x1b[42m{new}\x1b[0m\x1b[K")
+            }
+            Change::ReplaceAll(range, vec) => {
+                let parent = range.start().parent().unwrap();
+                let parent_str = parent.to_string();
+                let pre_range =
+                    TextRange::new(parent.text_range().start(), range.start().text_range().start());
+                let old_range = TextRange::new(
+                    range.start().text_range().start(),
+                    range.end().text_range().end(),
+                );
+                let post_range =
+                    TextRange::new(range.end().text_range().end(), parent.text_range().end());
+
+                let pre_str = &parent_str[pre_range - parent.text_range().start()];
+                let old_str = &parent_str[old_range - parent.text_range().start()];
+                let post_str = &parent_str[post_range - parent.text_range().start()];
+                let new: String = vec.iter().map(|it| it.to_string()).collect();
+
+                write!(f, "{pre_str}\x1b[41m{old_str}\x1b[42m{new}\x1b[0m\x1b[K{post_str}")
+            }
+        }
+    }
+}
+
 /// Utility trait to allow calling syntax editor functions with references or owned
 /// nodes. Do not use outside of this module.
 pub trait Element {
diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs
index 57ecbe57019..fa51fb6eef4 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/edit_algo.rs
@@ -1,9 +1,14 @@
 //! Implementation of applying changes to a syntax tree.
 
-use std::{cmp::Ordering, collections::VecDeque, ops::RangeInclusive};
+use std::{
+    cmp::Ordering,
+    collections::VecDeque,
+    ops::{Range, RangeInclusive},
+};
 
 use rowan::TextRange;
 use rustc_hash::FxHashMap;
+use stdx::format_to;
 
 use crate::{
     syntax_editor::{mapping::MissingMapping, Change, ChangeKind, PositionRepr},
@@ -76,11 +81,9 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
                 || (l.target_range().end() <= r.target_range().start())
         });
 
-    if stdx::never!(
-        !disjoint_replaces_ranges,
-        "some replace change ranges intersect: {:?}",
-        changes
-    ) {
+    if !disjoint_replaces_ranges {
+        report_intersecting_changes(&changes, get_node_depth, &root);
+
         return SyntaxEdit {
             old_root: root.clone(),
             new_root: root,
@@ -99,6 +102,7 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
     let mut changed_ancestors: VecDeque<ChangedAncestor> = VecDeque::new();
     let mut dependent_changes = vec![];
     let mut independent_changes = vec![];
+    let mut outdated_changes = vec![];
 
     for (change_index, change) in changes.iter().enumerate() {
         // Check if this change is dependent on another change (i.e. it's contained within another range)
@@ -113,10 +117,14 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
             // FIXME: Resolve changes that depend on a range of elements
             let ancestor = &changed_ancestors[index];
 
-            dependent_changes.push(DependentChange {
-                parent: ancestor.change_index as u32,
-                child: change_index as u32,
-            });
+            if let Change::Replace(_, None) = changes[ancestor.change_index] {
+                outdated_changes.push(change_index as u32);
+            } else {
+                dependent_changes.push(DependentChange {
+                    parent: ancestor.change_index as u32,
+                    child: change_index as u32,
+                });
+            }
         } else {
             // This change is independent of any other change
 
@@ -192,8 +200,9 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
             Change::Replace(target, Some(new_target)) => {
                 (to_owning_node(target), to_owning_node(new_target))
             }
-            // Silently drop outdated change
-            Change::Replace(_, None) => continue,
+            Change::Replace(_, None) => {
+                unreachable!("deletions should not generate dependent changes")
+            }
             Change::ReplaceAll(_, _) | Change::ReplaceWithMany(_, _) => {
                 unimplemented!("cannot resolve changes that depend on replacing many elements")
             }
@@ -231,6 +240,12 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
         }
     }
 
+    // We reverse here since we pushed to this in ascending order,
+    // and we want to remove elements in descending order
+    for idx in outdated_changes.into_iter().rev() {
+        changes.remove(idx as usize);
+    }
+
     // Apply changes
     let mut root = tree_mutator.mutable_clone;
 
@@ -293,6 +308,78 @@ pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
     }
 }
 
+fn report_intersecting_changes(
+    changes: &[Change],
+    mut get_node_depth: impl FnMut(rowan::SyntaxNode<crate::RustLanguage>) -> usize,
+    root: &rowan::SyntaxNode<crate::RustLanguage>,
+) {
+    let intersecting_changes = changes
+        .iter()
+        .zip(changes.iter().skip(1))
+        .filter(|(l, r)| {
+            // We only care about checking for disjoint replace ranges.
+            matches!(
+                (l.change_kind(), r.change_kind()),
+                (
+                    ChangeKind::Replace | ChangeKind::ReplaceRange,
+                    ChangeKind::Replace | ChangeKind::ReplaceRange
+                )
+            )
+        })
+        .filter(|(l, r)| {
+            get_node_depth(l.target_parent()) == get_node_depth(r.target_parent())
+                && (l.target_range().end() > r.target_range().start())
+        });
+
+    let mut error_msg = String::from("some replace change ranges intersect!\n");
+
+    let parent_str = root.to_string();
+
+    for (l, r) in intersecting_changes {
+        let mut highlighted_str = parent_str.clone();
+        let l_range = l.target_range();
+        let r_range = r.target_range();
+
+        let i_range = l_range.intersect(r_range).unwrap();
+        let i_str = format!("\x1b[46m{}", &parent_str[i_range]);
+
+        let pre_range: Range<usize> = l_range.start().into()..i_range.start().into();
+        let pre_str = format!("\x1b[44m{}", &parent_str[pre_range]);
+
+        let (highlight_range, highlight_str) = if l_range == r_range {
+            format_to!(error_msg, "\x1b[46mleft change:\x1b[0m  {l:?} {l}\n");
+            format_to!(error_msg, "\x1b[46mequals\x1b[0m\n");
+            format_to!(error_msg, "\x1b[46mright change:\x1b[0m {r:?} {r}\n");
+            let i_highlighted = format!("{i_str}\x1b[0m\x1b[K");
+            let total_range: Range<usize> = i_range.into();
+            (total_range, i_highlighted)
+        } else {
+            format_to!(error_msg, "\x1b[44mleft change:\x1b[0m  {l:?} {l}\n");
+            let range_end = if l_range.contains_range(r_range) {
+                format_to!(error_msg, "\x1b[46mcovers\x1b[0m\n");
+                format_to!(error_msg, "\x1b[46mright change:\x1b[0m {r:?} {r}\n");
+                l_range.end()
+            } else {
+                format_to!(error_msg, "\x1b[46mintersects\x1b[0m\n");
+                format_to!(error_msg, "\x1b[42mright change:\x1b[0m {r:?} {r}\n");
+                r_range.end()
+            };
+
+            let post_range: Range<usize> = i_range.end().into()..range_end.into();
+
+            let post_str = format!("\x1b[42m{}", &parent_str[post_range]);
+            let result = format!("{pre_str}{i_str}{post_str}\x1b[0m\x1b[K");
+            let total_range: Range<usize> = l_range.start().into()..range_end.into();
+            (total_range, result)
+        };
+        highlighted_str.replace_range(highlight_range, &highlight_str);
+
+        format_to!(error_msg, "{highlighted_str}\n");
+    }
+
+    stdx::always!(false, "{}", error_msg);
+}
+
 fn to_owning_node(element: &SyntaxElement) -> SyntaxNode {
     match element {
         SyntaxElement::Node(node) => node.clone(),
diff --git a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs
index 16bc55ed2d4..f71925a7955 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/syntax_editor/mapping.rs
@@ -239,10 +239,10 @@ impl SyntaxMappingBuilder {
 
     pub fn map_children(
         &mut self,
-        input: impl Iterator<Item = SyntaxNode>,
-        output: impl Iterator<Item = SyntaxNode>,
+        input: impl IntoIterator<Item = SyntaxNode>,
+        output: impl IntoIterator<Item = SyntaxNode>,
     ) {
-        for pairs in input.zip_longest(output) {
+        for pairs in input.into_iter().zip_longest(output) {
             let (input, output) = match pairs {
                 itertools::EitherOrBoth::Both(l, r) => (l, r),
                 itertools::EitherOrBoth::Left(_) => {
diff --git a/src/tools/rust-analyzer/crates/test-utils/Cargo.toml b/src/tools/rust-analyzer/crates/test-utils/Cargo.toml
index b1457722a92..b99a2c4bd75 100644
--- a/src/tools/rust-analyzer/crates/test-utils/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/test-utils/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 # Avoid adding deps here, this crate is widely used in tests it should compile fast!
diff --git a/src/tools/rust-analyzer/crates/test-utils/src/assert_linear.rs b/src/tools/rust-analyzer/crates/test-utils/src/assert_linear.rs
index 15c30c52a54..f78bf59a2fd 100644
--- a/src/tools/rust-analyzer/crates/test-utils/src/assert_linear.rs
+++ b/src/tools/rust-analyzer/crates/test-utils/src/assert_linear.rs
@@ -11,7 +11,7 @@
 //! Ideally, we should use a proper "model selection" to directly compare
 //! quadratic and linear models, but that sounds rather complicated:
 //!
-//!     https://stats.stackexchange.com/questions/21844/selecting-best-model-based-on-linear-quadratic-and-cubic-fit-of-data
+//! > https://stats.stackexchange.com/questions/21844/selecting-best-model-based-on-linear-quadratic-and-cubic-fit-of-data
 //!
 //! We might get false positives on a VM, but never false negatives. So, if the
 //! first round fails, we repeat the ordeal three more times and fail only if
diff --git a/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs b/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs
index 7fe26d53bf2..7240069753e 100644
--- a/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs
+++ b/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs
@@ -6,7 +6,8 @@
 //! Use this to test functionality local to one file.
 //!
 //! Simple Example:
-//! ```
+//!
+//! ```ignore
 //! r#"
 //! fn main() {
 //!     println!("Hello World")
@@ -19,7 +20,8 @@
 //! which is also how to define multiple files in a single test fixture
 //!
 //! Example using two files in the same crate:
-//! ```
+//!
+//! ```ignore
 //! "
 //! //- /main.rs
 //! mod foo;
@@ -33,7 +35,8 @@
 //! ```
 //!
 //! Example using two crates with one file each, with one crate depending on the other:
-//! ```
+//!
+//! ```ignore
 //! r#"
 //! //- /main.rs crate:a deps:b
 //! fn main() {
@@ -51,7 +54,8 @@
 //! for the syntax.
 //!
 //! Example using some available metadata:
-//! ```
+//!
+//! ```ignore
 //! "
 //! //- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo
 //! fn insert_source_code_here() {}
@@ -214,16 +218,11 @@ impl FixtureWithProjectMeta {
                 );
             }
 
-            if line.starts_with("//-") {
+            if let Some(line) = line.strip_prefix("//-") {
                 let meta = Self::parse_meta_line(line);
                 res.push(meta);
             } else {
-                if line.starts_with("// ")
-                    && line.contains(':')
-                    && !line.contains("::")
-                    && !line.contains('.')
-                    && line.chars().all(|it| !it.is_uppercase())
-                {
+                if matches!(line.strip_prefix("// "), Some(l) if l.trim().starts_with('/')) {
                     panic!("looks like invalid metadata line: {line:?}");
                 }
 
@@ -238,8 +237,7 @@ impl FixtureWithProjectMeta {
 
     //- /lib.rs crate:foo deps:bar,baz cfg:foo=a,bar=b env:OUTDIR=path/to,OTHER=foo
     fn parse_meta_line(meta: &str) -> Fixture {
-        assert!(meta.starts_with("//-"));
-        let meta = meta["//-".len()..].trim();
+        let meta = meta.trim();
         let mut components = meta.split_ascii_whitespace();
 
         let path = components.next().expect("fixture meta must start with a path").to_owned();
diff --git a/src/tools/rust-analyzer/crates/test-utils/src/lib.rs b/src/tools/rust-analyzer/crates/test-utils/src/lib.rs
index e7279fa1f66..d3afac85017 100644
--- a/src/tools/rust-analyzer/crates/test-utils/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/test-utils/src/lib.rs
@@ -421,8 +421,8 @@ pub fn format_diff(chunks: Vec<dissimilar::Chunk<'_>>) -> String {
     for chunk in chunks {
         let formatted = match chunk {
             dissimilar::Chunk::Equal(text) => text.into(),
-            dissimilar::Chunk::Delete(text) => format!("\x1b[41m{text}\x1b[0m"),
-            dissimilar::Chunk::Insert(text) => format!("\x1b[42m{text}\x1b[0m"),
+            dissimilar::Chunk::Delete(text) => format!("\x1b[41m{text}\x1b[0m\x1b[K"),
+            dissimilar::Chunk::Insert(text) => format!("\x1b[42m{text}\x1b[0m\x1b[K"),
         };
         buf.push_str(&formatted);
     }
diff --git a/src/tools/rust-analyzer/crates/toolchain/Cargo.toml b/src/tools/rust-analyzer/crates/toolchain/Cargo.toml
index 87e8efb20fc..38daacdf951 100644
--- a/src/tools/rust-analyzer/crates/toolchain/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/toolchain/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 home = "0.5.4"
diff --git a/src/tools/rust-analyzer/crates/tt/Cargo.toml b/src/tools/rust-analyzer/crates/tt/Cargo.toml
index 82e7c24668f..529fad3244a 100644
--- a/src/tools/rust-analyzer/crates/tt/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/tt/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 arrayvec.workspace = true
diff --git a/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml b/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml
index bc54d7168f0..48b4d22de2f 100644
--- a/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/vfs-notify/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 tracing.workspace = true
diff --git a/src/tools/rust-analyzer/crates/vfs/Cargo.toml b/src/tools/rust-analyzer/crates/vfs/Cargo.toml
index e8a6195036e..546195481c6 100644
--- a/src/tools/rust-analyzer/crates/vfs/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/vfs/Cargo.toml
@@ -10,7 +10,6 @@ license.workspace = true
 rust-version.workspace = true
 
 [lib]
-doctest = false
 
 [dependencies]
 rustc-hash.workspace = true
diff --git a/src/tools/rust-analyzer/crates/vfs/src/anchored_path.rs b/src/tools/rust-analyzer/crates/vfs/src/anchored_path.rs
index db15a2a21cd..1b9fb355b48 100644
--- a/src/tools/rust-analyzer/crates/vfs/src/anchored_path.rs
+++ b/src/tools/rust-analyzer/crates/vfs/src/anchored_path.rs
@@ -2,7 +2,7 @@
 //!
 //! The primary goal of this is to losslessly represent paths like
 //!
-//! ```
+//! ```ignore
 //! #[path = "./bar.rs"]
 //! mod foo;
 //! ```
diff --git a/src/tools/rust-analyzer/crates/vfs/src/vfs_path.rs b/src/tools/rust-analyzer/crates/vfs/src/vfs_path.rs
index 3c8e37413f6..cce8595cc4a 100644
--- a/src/tools/rust-analyzer/crates/vfs/src/vfs_path.rs
+++ b/src/tools/rust-analyzer/crates/vfs/src/vfs_path.rs
@@ -59,7 +59,7 @@ impl VfsPath {
     ///
     /// # Example
     ///
-    /// ```
+    /// ```ignore
     /// # use vfs::{AbsPathBuf, VfsPath};
     /// let mut path = VfsPath::from(AbsPathBuf::assert("/foo/bar".into()));
     /// assert!(path.pop());
diff --git a/src/tools/rust-analyzer/docs/book/src/assists_generated.md b/src/tools/rust-analyzer/docs/book/src/assists_generated.md
index 9d68a873ffe..c2063df5068 100644
--- a/src/tools/rust-analyzer/docs/book/src/assists_generated.md
+++ b/src/tools/rust-analyzer/docs/book/src/assists_generated.md
@@ -257,7 +257,7 @@ fn main() {
 
 
 ### `apply_demorgan`
-**Source:**  [apply_demorgan.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/apply_demorgan.rs#L16) 
+**Source:**  [apply_demorgan.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/apply_demorgan.rs#L23) 
 
 Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws).
 This transforms expressions of the form `!l || !r` into `!(l && r)`.
@@ -280,7 +280,7 @@ fn main() {
 
 
 ### `apply_demorgan_iterator`
-**Source:**  [apply_demorgan.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/apply_demorgan.rs#L132) 
+**Source:**  [apply_demorgan.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/apply_demorgan.rs#L154) 
 
 Apply [De Morgan's law](https://en.wikipedia.org/wiki/De_Morgan%27s_laws) to
 `Iterator::all` and `Iterator::any`.
@@ -419,7 +419,7 @@ Converts comments to documentation.
 
 
 ### `convert_bool_then_to_if`
-**Source:**  [convert_bool_then.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_bool_then.rs#L131) 
+**Source:**  [convert_bool_then.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_bool_then.rs#L143) 
 
 Converts a `bool::then` method call to an equivalent if expression.
 
@@ -443,7 +443,7 @@ fn main() {
 
 
 ### `convert_closure_to_fn`
-**Source:**  [convert_closure_to_fn.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_closure_to_fn.rs#L25) 
+**Source:**  [convert_closure_to_fn.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_closure_to_fn.rs#L27) 
 
 This converts a closure to a freestanding function, changing all captures to parameters.
 
@@ -527,7 +527,7 @@ impl TryFrom<usize> for Thing {
 
 
 ### `convert_if_to_bool_then`
-**Source:**  [convert_bool_then.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_bool_then.rs#L20) 
+**Source:**  [convert_bool_then.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/convert_bool_then.rs#L21) 
 
 Converts an if expression into a corresponding `bool::then` call.
 
@@ -1345,6 +1345,26 @@ fn main() {
 ```
 
 
+### `flip_or_pattern`
+**Source:**  [flip_or_pattern.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/flip_or_pattern.rs#L9) 
+
+Flips two trait bounds.
+
+#### Before
+```rust
+fn foo() {
+    let (a |┃ b) = 1;
+}
+```
+
+#### After
+```rust
+fn foo() {
+    let (b | a) = 1;
+}
+```
+
+
 ### `flip_trait_bound`
 **Source:**  [flip_trait_bound.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/flip_trait_bound.rs#L9) 
 
@@ -2161,7 +2181,7 @@ struct Ctx<T: Clone> {
     data: T,
 }
 
-impl<T: Clone> ${0:_} for Ctx<T> {}
+impl<T: Clone> ${1:_} for Ctx<T> {┃}
 ```
 
 
@@ -2258,7 +2278,7 @@ fn bar() {
 
 
 ### `inline_local_variable`
-**Source:**  [inline_local_variable.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/inline_local_variable.rs#L17) 
+**Source:**  [inline_local_variable.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/inline_local_variable.rs#L21) 
 
 Inlines a local variable.
 
@@ -2974,7 +2994,7 @@ impl Walrus {
 
 
 ### `remove_parentheses`
-**Source:**  [remove_parentheses.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/remove_parentheses.rs#L5) 
+**Source:**  [remove_parentheses.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/remove_parentheses.rs#L9) 
 
 Removes redundant parentheses.
 
@@ -3015,7 +3035,7 @@ mod foo {
 
 
 ### `remove_unused_param`
-**Source:**  [remove_unused_param.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/remove_unused_param.rs#L15) 
+**Source:**  [remove_unused_param.rs](https://github.com/rust-lang/rust-analyzer/blob/master/crates/ide-assists/src/handlers/remove_unused_param.rs#L16) 
 
 Removes unused function parameter.
 
diff --git a/src/tools/rust-analyzer/docs/book/src/configuration_generated.md b/src/tools/rust-analyzer/docs/book/src/configuration_generated.md
index 0c6674b1408..1cbe51836f4 100644
--- a/src/tools/rust-analyzer/docs/book/src/configuration_generated.md
+++ b/src/tools/rust-analyzer/docs/book/src/configuration_generated.md
@@ -559,6 +559,11 @@ also need to add the folders to Code's `files.watcherExclude`.
 `#rust-analyzer.hover.documentation.enable#` is set.
 
 
+**rust-analyzer.hover.dropGlue.enable** (default: true)
+
+ Whether to show drop glue information on hover.
+
+
 **rust-analyzer.hover.links.enable** (default: true)
 
  Use markdown syntax for links on hover.
diff --git a/src/tools/rust-analyzer/docs/book/src/contributing/setup.md b/src/tools/rust-analyzer/docs/book/src/contributing/setup.md
index d8a7840d376..eab65e779ed 100644
--- a/src/tools/rust-analyzer/docs/book/src/contributing/setup.md
+++ b/src/tools/rust-analyzer/docs/book/src/contributing/setup.md
@@ -17,10 +17,13 @@ Since rust-analyzer is a Rust project, you will need to install Rust. You can do
 **Step 04**: Install the language server locally by running the following command:
 
 ```sh
-cargo xtask install --server --code-bin code-insiders --dev-rel
+# Install only the language server  
+cargo xtask install --server \  
+    --code-bin code-insiders \  # Target a specific editor (code, code-exploration, code-insiders, codium, or code-oss)  
+    --dev-rel  # Build in release mode with debug info level 2  
 ```
 
-In the output of this command, there should be a file path provided to the installed binary on  your local machine.
+In the output of this command, there should be a file path provided to the installed binary on your local machine.
 It should look something like the following output below:
 
 ```
@@ -48,9 +51,12 @@ An example debugging statement could go into the `main_loop.rs` file which can b
 ```rs
 eprintln!("Hello, world!");
 ```
+Now, run the following commands to check the project and reinstall the server:  
 
-Now we run `cargo build` and `sh
-cargo xtask install --server --code-bin code-insiders --dev-rel` to reinstall the server.
+```sh  
+cargo check  
+cargo xtask install --server --code-bin code-insiders --dev-rel  
+```  
 
 Now on Visual Studio Code Insiders, we should be able to open the Output tab on our terminal and switch to Rust Analyzer Language Server to see the `eprintln!` statement we just wrote.
 
diff --git a/src/tools/rust-analyzer/editors/code/.eslintignore b/src/tools/rust-analyzer/editors/code/.eslintignore
deleted file mode 100644
index 3a1e8e186f5..00000000000
--- a/src/tools/rust-analyzer/editors/code/.eslintignore
+++ /dev/null
@@ -1,2 +0,0 @@
-node_modules
-.eslintrc.js
diff --git a/src/tools/rust-analyzer/editors/code/.eslintrc.js b/src/tools/rust-analyzer/editors/code/.eslintrc.js
deleted file mode 100644
index 9705c5f5ec6..00000000000
--- a/src/tools/rust-analyzer/editors/code/.eslintrc.js
+++ /dev/null
@@ -1,46 +0,0 @@
-module.exports = {
-    env: {
-        es6: true,
-        node: true,
-    },
-    extends: ["prettier"],
-    parser: "@typescript-eslint/parser",
-    parserOptions: {
-        project: true,
-        tsconfigRootDir: __dirname,
-        sourceType: "module",
-    },
-    plugins: ["@typescript-eslint"],
-    rules: {
-        camelcase: ["error"],
-        eqeqeq: ["error", "always", { null: "ignore" }],
-        curly: ["error", "multi-line"],
-        "no-console": ["error", { allow: ["warn", "error"] }],
-        "prefer-const": "error",
-        "@typescript-eslint/member-delimiter-style": [
-            "error",
-            {
-                multiline: {
-                    delimiter: "semi",
-                    requireLast: true,
-                },
-                singleline: {
-                    delimiter: "semi",
-                    requireLast: false,
-                },
-            },
-        ],
-        "@typescript-eslint/semi": ["error", "always"],
-        "@typescript-eslint/no-unnecessary-type-assertion": "error",
-        "@typescript-eslint/no-floating-promises": "error",
-
-        "@typescript-eslint/consistent-type-imports": [
-            "error",
-            {
-                prefer: "type-imports",
-                fixStyle: "inline-type-imports",
-            },
-        ],
-        "@typescript-eslint/no-import-type-side-effects": "error",
-    },
-};
diff --git a/src/tools/rust-analyzer/editors/code/.prettierrc.js b/src/tools/rust-analyzer/editors/code/.prettierrc.js
deleted file mode 100644
index cafb12f0e6d..00000000000
--- a/src/tools/rust-analyzer/editors/code/.prettierrc.js
+++ /dev/null
@@ -1,5 +0,0 @@
-module.exports = {
-    // use 100 because it's Rustfmt's default
-    // https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#max_width
-    printWidth: 100,
-};
diff --git a/src/tools/rust-analyzer/editors/code/eslint.config.mts b/src/tools/rust-analyzer/editors/code/eslint.config.mts
new file mode 100644
index 00000000000..3520593eef2
--- /dev/null
+++ b/src/tools/rust-analyzer/editors/code/eslint.config.mts
@@ -0,0 +1,48 @@
+import eslintConfigPrettier from "eslint-config-prettier";
+import stylistic from "@stylistic/eslint-plugin";
+import eslint from "@eslint/js";
+import tseslint from "typescript-eslint";
+import stylisticJs from "@stylistic/eslint-plugin-js";
+import { type FlatESLintConfig } from "eslint-define-config";
+
+const config: FlatESLintConfig[] = [
+    eslintConfigPrettier,
+    eslint.configs.recommended,
+    stylisticJs.configs["disable-legacy"],
+    ...tseslint.configs.recommended,
+    stylistic.configs.customize({
+        indent: 4,
+        quotes: "double",
+        semi: true,
+        braceStyle: "1tbs",
+        arrowParens: true,
+    }),
+    {
+        rules: {
+            "no-console": "warn",
+            "@typescript-eslint/no-unused-vars": [
+                "error",
+                {
+                    args: "all",
+                    argsIgnorePattern: "^_",
+                    caughtErrors: "all",
+                    caughtErrorsIgnorePattern: "^_",
+                    destructuredArrayIgnorePattern: "^_",
+                    varsIgnorePattern: "^_",
+                    ignoreRestSiblings: true,
+                },
+            ],
+            // the following stylistic lints conflict with prettier
+            "@stylistic/operator-linebreak": "off",
+            "@stylistic/indent-binary-ops": "off",
+            "@stylistic/indent": "off",
+            "@stylistic/brace-style": "off",
+            "@stylistic/quotes": "off",
+        },
+    },
+    {
+        ignores: ["out/", ".vscode-test/", "node_modules/"],
+    },
+];
+
+export default config;
diff --git a/src/tools/rust-analyzer/editors/code/package-lock.json b/src/tools/rust-analyzer/editors/code/package-lock.json
index 86a066454a5..11a37c218f7 100644
--- a/src/tools/rust-analyzer/editors/code/package-lock.json
+++ b/src/tools/rust-analyzer/editors/code/package-lock.json
@@ -9,39 +9,36 @@
             "version": "0.5.0-dev",
             "license": "MIT OR Apache-2.0",
             "dependencies": {
-                "@hpcc-js/wasm": "^2.13.0",
-                "anser": "^2.1.1",
-                "d3": "^7.8.5",
-                "d3-graphviz": "^5.0.2",
+                "@hpcc-js/wasm": "^2.22.4",
+                "anser": "^2.3.2",
+                "d3": "^7.9.0",
+                "d3-graphviz": "^5.6.0",
+                "jiti": "^2.4.2",
                 "vscode-languageclient": "^9.0.1"
             },
             "devDependencies": {
-                "@tsconfig/strictest": "^2.0.1",
-                "@types/node": "~16.11.7",
-                "@types/vscode": "~1.83",
-                "@typescript-eslint/eslint-plugin": "^6.0.0",
-                "@typescript-eslint/parser": "^6.0.0",
-                "@vscode/test-electron": "^2.3.8",
-                "@vscode/vsce": "^3.0.0",
+                "@eslint/js": "^9.21.0",
+                "@stylistic/eslint-plugin": "^4.1.0",
+                "@stylistic/eslint-plugin-js": "^4.1.0",
+                "@tsconfig/strictest": "^2.0.5",
+                "@types/node": "~22.13.4",
+                "@types/vscode": "~1.93.0",
+                "@typescript-eslint/eslint-plugin": "^8.25.0",
+                "@typescript-eslint/parser": "^8.25.0",
+                "@vscode/test-electron": "^2.4.1",
+                "@vscode/vsce": "^3.2.2",
                 "esbuild": "^0.25.0",
-                "eslint": "^8.44.0",
-                "eslint-config-prettier": "^8.8.0",
-                "ovsx": "^0.8.2",
-                "prettier": "^3.0.0",
-                "tslib": "^2.6.0",
-                "typescript": "^5.6.0"
+                "eslint": "^9.21.0",
+                "eslint-config-prettier": "^10.0.2",
+                "eslint-define-config": "^2.1.0",
+                "ovsx": "0.10.1",
+                "prettier": "^3.5.2",
+                "tslib": "^2.8.1",
+                "typescript": "^5.7.3",
+                "typescript-eslint": "^8.25.0"
             },
             "engines": {
-                "vscode": "^1.83.0"
-            }
-        },
-        "node_modules/@aashutoshrathi/word-wrap": {
-            "version": "1.2.6",
-            "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
-            "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
-            "dev": true,
-            "engines": {
-                "node": ">=0.10.0"
+                "vscode": "^1.93.0"
             }
         },
         "node_modules/@azure/abort-controller": {
@@ -92,16 +89,16 @@
             }
         },
         "node_modules/@azure/core-rest-pipeline": {
-            "version": "1.17.0",
-            "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.17.0.tgz",
-            "integrity": "sha512-62Vv8nC+uPId3j86XJ0WI+sBf0jlqTqPUFCBNrGtlaUeQUIXWV/D8GE5A1d+Qx8H7OQojn2WguC8kChD6v0shA==",
+            "version": "1.19.0",
+            "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.19.0.tgz",
+            "integrity": "sha512-bM3308LRyg5g7r3Twprtqww0R/r7+GyVxj4BafcmVPo4WQoGt5JXuaqxHEFjw2o3rvFZcUPiqJMg6WuvEEeVUA==",
             "dev": true,
             "license": "MIT",
             "dependencies": {
                 "@azure/abort-controller": "^2.0.0",
                 "@azure/core-auth": "^1.8.0",
                 "@azure/core-tracing": "^1.0.1",
-                "@azure/core-util": "^1.9.0",
+                "@azure/core-util": "^1.11.0",
                 "@azure/logger": "^1.0.0",
                 "http-proxy-agent": "^7.0.0",
                 "https-proxy-agent": "^7.0.0",
@@ -111,47 +108,6 @@
                 "node": ">=18.0.0"
             }
         },
-        "node_modules/@azure/core-rest-pipeline/node_modules/agent-base": {
-            "version": "7.1.1",
-            "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
-            "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
-            "dev": true,
-            "license": "MIT",
-            "dependencies": {
-                "debug": "^4.3.4"
-            },
-            "engines": {
-                "node": ">= 14"
-            }
-        },
-        "node_modules/@azure/core-rest-pipeline/node_modules/http-proxy-agent": {
-            "version": "7.0.2",
-            "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
-            "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
-            "dev": true,
-            "license": "MIT",
-            "dependencies": {
-                "agent-base": "^7.1.0",
-                "debug": "^4.3.4"
-            },
-            "engines": {
-                "node": ">= 14"
-            }
-        },
-        "node_modules/@azure/core-rest-pipeline/node_modules/https-proxy-agent": {
-            "version": "7.0.5",
-            "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz",
-            "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==",
-            "dev": true,
-            "license": "MIT",
-            "dependencies": {
-                "agent-base": "^7.0.2",
-                "debug": "4"
-            },
-            "engines": {
-                "node": ">= 14"
-            }
-        },
         "node_modules/@azure/core-tracing": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.2.0.tgz",
@@ -180,9 +136,9 @@
             }
         },
         "node_modules/@azure/identity": {
-            "version": "4.5.0",
-            "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.5.0.tgz",
-            "integrity": "sha512-EknvVmtBuSIic47xkOqyNabAme0RYTw52BTMz8eBgU1ysTyMrD1uOoM+JdS0J/4Yfp98IBT3osqq3BfwSaNaGQ==",
+            "version": "4.7.0",
+            "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.7.0.tgz",
+            "integrity": "sha512-6z/S2KorkbKaZ0DgZFVRdu7RCuATmMSTjKpuhj7YpjxkJ0vnJ7kTM3cpNgzFgk9OPYfZ31wrBEtC/iwAS4jQDA==",
             "dev": true,
             "license": "MIT",
             "dependencies": {
@@ -193,11 +149,11 @@
                 "@azure/core-tracing": "^1.0.0",
                 "@azure/core-util": "^1.11.0",
                 "@azure/logger": "^1.0.0",
-                "@azure/msal-browser": "^3.26.1",
-                "@azure/msal-node": "^2.15.0",
+                "@azure/msal-browser": "^4.2.0",
+                "@azure/msal-node": "^3.2.1",
                 "events": "^3.0.0",
                 "jws": "^4.0.0",
-                "open": "^8.0.0",
+                "open": "^10.1.0",
                 "stoppable": "^1.1.0",
                 "tslib": "^2.2.0"
             },
@@ -219,22 +175,22 @@
             }
         },
         "node_modules/@azure/msal-browser": {
-            "version": "3.26.1",
-            "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-3.26.1.tgz",
-            "integrity": "sha512-y78sr9g61aCAH9fcLO1um+oHFXc1/5Ap88RIsUSuzkm0BHzFnN+PXGaQeuM1h5Qf5dTnWNOd6JqkskkMPAhh7Q==",
+            "version": "4.4.0",
+            "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-4.4.0.tgz",
+            "integrity": "sha512-rU6juYXk67CKQmpgi6fDgZoPQ9InZ1760z1BSAH7RbeIc4lHZM/Tu+H0CyRk7cnrfvTkexyYE4pjYhMghpzheA==",
             "dev": true,
             "license": "MIT",
             "dependencies": {
-                "@azure/msal-common": "14.15.0"
+                "@azure/msal-common": "15.2.0"
             },
             "engines": {
                 "node": ">=0.8.0"
             }
         },
         "node_modules/@azure/msal-common": {
-            "version": "14.15.0",
-            "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.15.0.tgz",
-            "integrity": "sha512-ImAQHxmpMneJ/4S8BRFhjt1MZ3bppmpRPYYNyzeQPeFN288YKbb8TmmISQEbtfkQ1BPASvYZU5doIZOPBAqENQ==",
+            "version": "15.2.0",
+            "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-15.2.0.tgz",
+            "integrity": "sha512-HiYfGAKthisUYqHG1nImCf/uzcyS31wng3o+CycWLIM9chnYJ9Lk6jZ30Y6YiYYpTQ9+z/FGUpiKKekd3Arc0A==",
             "dev": true,
             "license": "MIT",
             "engines": {
@@ -242,13 +198,13 @@
             }
         },
         "node_modules/@azure/msal-node": {
-            "version": "2.15.0",
-            "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-2.15.0.tgz",
-            "integrity": "sha512-gVPW8YLz92ZeCibQH2QUw96odJoiM3k/ZPH3f2HxptozmH6+OnyyvKXo/Egg39HAM230akarQKHf0W74UHlh0Q==",
+            "version": "3.2.3",
+            "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-3.2.3.tgz",
+            "integrity": "sha512-0eaPqBIWEAizeYiXdeHb09Iq0tvHJ17ztvNEaLdr/KcJJhJxbpkkEQf09DB+vKlFE0tzYi7j4rYLTXtES/InEQ==",
             "dev": true,
             "license": "MIT",
             "dependencies": {
-                "@azure/msal-common": "14.15.0",
+                "@azure/msal-common": "15.2.0",
                 "jsonwebtoken": "^9.0.0",
                 "uuid": "^8.3.0"
             },
@@ -682,39 +638,110 @@
             }
         },
         "node_modules/@eslint-community/eslint-utils": {
-            "version": "4.4.0",
-            "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
-            "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+            "version": "4.4.1",
+            "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz",
+            "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "eslint-visitor-keys": "^3.3.0"
+                "eslint-visitor-keys": "^3.4.3"
             },
             "engines": {
                 "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
             },
+            "funding": {
+                "url": "https://opencollective.com/eslint"
+            },
             "peerDependencies": {
                 "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
             }
         },
+        "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
+            "version": "3.4.3",
+            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+            "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+            "dev": true,
+            "license": "Apache-2.0",
+            "engines": {
+                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/eslint"
+            }
+        },
         "node_modules/@eslint-community/regexpp": {
-            "version": "4.5.1",
-            "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz",
-            "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==",
+            "version": "4.12.1",
+            "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
+            "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
             }
         },
+        "node_modules/@eslint/config-array": {
+            "version": "0.19.2",
+            "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.2.tgz",
+            "integrity": "sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==",
+            "dev": true,
+            "license": "Apache-2.0",
+            "dependencies": {
+                "@eslint/object-schema": "^2.1.6",
+                "debug": "^4.3.1",
+                "minimatch": "^3.1.2"
+            },
+            "engines": {
+                "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+            }
+        },
+        "node_modules/@eslint/config-array/node_modules/brace-expansion": {
+            "version": "1.1.11",
+            "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+            "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "balanced-match": "^1.0.0",
+                "concat-map": "0.0.1"
+            }
+        },
+        "node_modules/@eslint/config-array/node_modules/minimatch": {
+            "version": "3.1.2",
+            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+            "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+            "dev": true,
+            "license": "ISC",
+            "dependencies": {
+                "brace-expansion": "^1.1.7"
+            },
+            "engines": {
+                "node": "*"
+            }
+        },
+        "node_modules/@eslint/core": {
+            "version": "0.12.0",
+            "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz",
+            "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==",
+            "dev": true,
+            "license": "Apache-2.0",
+            "dependencies": {
+                "@types/json-schema": "^7.0.15"
+            },
+            "engines": {
+                "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+            }
+        },
         "node_modules/@eslint/eslintrc": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz",
-            "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==",
+            "version": "3.3.0",
+            "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.0.tgz",
+            "integrity": "sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "ajv": "^6.12.4",
                 "debug": "^4.3.2",
-                "espree": "^9.6.0",
-                "globals": "^13.19.0",
+                "espree": "^10.0.1",
+                "globals": "^14.0.0",
                 "ignore": "^5.2.0",
                 "import-fresh": "^3.2.1",
                 "js-yaml": "^4.1.0",
@@ -722,166 +749,164 @@
                 "strip-json-comments": "^3.1.1"
             },
             "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+                "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
             },
             "funding": {
                 "url": "https://opencollective.com/eslint"
             }
         },
-        "node_modules/@eslint/js": {
-            "version": "8.44.0",
-            "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz",
-            "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==",
+        "node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
+            "version": "1.1.11",
+            "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+            "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
             "dev": true,
-            "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-            }
-        },
-        "node_modules/@hpcc-js/wasm": {
-            "version": "2.13.0",
-            "resolved": "https://registry.npmjs.org/@hpcc-js/wasm/-/wasm-2.13.0.tgz",
-            "integrity": "sha512-MvnUPnyMlN3/2IONCXwl/SBVWIfVOFJqvw+kFfI1QcwKjNmkwTAtG+9/m3nvofTymkASUUxNULbBmRDIr2uzIA==",
+            "license": "MIT",
             "dependencies": {
-                "yargs": "17.7.2"
-            },
-            "bin": {
-                "dot-wasm": "bin/dot-wasm.js"
+                "balanced-match": "^1.0.0",
+                "concat-map": "0.0.1"
             }
         },
-        "node_modules/@humanwhocodes/config-array": {
-            "version": "0.11.10",
-            "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz",
-            "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==",
+        "node_modules/@eslint/eslintrc/node_modules/minimatch": {
+            "version": "3.1.2",
+            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+            "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
             "dev": true,
+            "license": "ISC",
             "dependencies": {
-                "@humanwhocodes/object-schema": "^1.2.1",
-                "debug": "^4.1.1",
-                "minimatch": "^3.0.5"
+                "brace-expansion": "^1.1.7"
             },
             "engines": {
-                "node": ">=10.10.0"
+                "node": "*"
             }
         },
-        "node_modules/@humanwhocodes/module-importer": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
-            "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+        "node_modules/@eslint/js": {
+            "version": "9.21.0",
+            "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.21.0.tgz",
+            "integrity": "sha512-BqStZ3HX8Yz6LvsF5ByXYrtigrV5AXADWLAGc7PH/1SxOb7/FIYYMszZZWiUou/GB9P2lXWk2SV4d+Z8h0nknw==",
             "dev": true,
+            "license": "MIT",
             "engines": {
-                "node": ">=12.22"
-            },
-            "funding": {
-                "type": "github",
-                "url": "https://github.com/sponsors/nzakas"
+                "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
             }
         },
-        "node_modules/@humanwhocodes/object-schema": {
-            "version": "1.2.1",
-            "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
-            "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
-            "dev": true
+        "node_modules/@eslint/object-schema": {
+            "version": "2.1.6",
+            "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz",
+            "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==",
+            "dev": true,
+            "license": "Apache-2.0",
+            "engines": {
+                "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+            }
         },
-        "node_modules/@isaacs/cliui": {
-            "version": "8.0.2",
-            "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
-            "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+        "node_modules/@eslint/plugin-kit": {
+            "version": "0.2.7",
+            "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.7.tgz",
+            "integrity": "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==",
             "dev": true,
-            "license": "ISC",
+            "license": "Apache-2.0",
             "dependencies": {
-                "string-width": "^5.1.2",
-                "string-width-cjs": "npm:string-width@^4.2.0",
-                "strip-ansi": "^7.0.1",
-                "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
-                "wrap-ansi": "^8.1.0",
-                "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+                "@eslint/core": "^0.12.0",
+                "levn": "^0.4.1"
             },
             "engines": {
-                "node": ">=12"
+                "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
             }
         },
-        "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
-            "version": "6.1.0",
-            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
-            "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+        "node_modules/@hpcc-js/wasm": {
+            "version": "2.22.4",
+            "resolved": "https://registry.npmjs.org/@hpcc-js/wasm/-/wasm-2.22.4.tgz",
+            "integrity": "sha512-58JkRkxZffiBAbZhc7z+9iaaAOmn1cyxLL3rRwsUvco/I0Wwb7uVAlHM9HiU6XASe2k11jrIjCFff1t9QKjlqg==",
+            "license": "Apache-2.0",
+            "dependencies": {
+                "yargs": "17.7.2"
+            },
+            "bin": {
+                "dot-wasm": "node ./node_modules/@hpcc-js/wasm-graphviz-cli/bin/index.js"
+            }
+        },
+        "node_modules/@humanfs/core": {
+            "version": "0.19.1",
+            "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
+            "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
             "dev": true,
-            "license": "MIT",
+            "license": "Apache-2.0",
             "engines": {
-                "node": ">=12"
+                "node": ">=18.18.0"
+            }
+        },
+        "node_modules/@humanfs/node": {
+            "version": "0.16.6",
+            "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz",
+            "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==",
+            "dev": true,
+            "license": "Apache-2.0",
+            "dependencies": {
+                "@humanfs/core": "^0.19.1",
+                "@humanwhocodes/retry": "^0.3.0"
             },
-            "funding": {
-                "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+            "engines": {
+                "node": ">=18.18.0"
             }
         },
-        "node_modules/@isaacs/cliui/node_modules/ansi-styles": {
-            "version": "6.2.1",
-            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
-            "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+        "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": {
+            "version": "0.3.1",
+            "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz",
+            "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==",
             "dev": true,
-            "license": "MIT",
+            "license": "Apache-2.0",
             "engines": {
-                "node": ">=12"
+                "node": ">=18.18"
             },
             "funding": {
-                "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+                "type": "github",
+                "url": "https://github.com/sponsors/nzakas"
             }
         },
-        "node_modules/@isaacs/cliui/node_modules/emoji-regex": {
-            "version": "9.2.2",
-            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
-            "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
-            "dev": true,
-            "license": "MIT"
-        },
-        "node_modules/@isaacs/cliui/node_modules/string-width": {
-            "version": "5.1.2",
-            "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
-            "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+        "node_modules/@humanwhocodes/module-importer": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+            "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
             "dev": true,
-            "license": "MIT",
-            "dependencies": {
-                "eastasianwidth": "^0.2.0",
-                "emoji-regex": "^9.2.2",
-                "strip-ansi": "^7.0.1"
-            },
+            "license": "Apache-2.0",
             "engines": {
-                "node": ">=12"
+                "node": ">=12.22"
             },
             "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
+                "type": "github",
+                "url": "https://github.com/sponsors/nzakas"
             }
         },
-        "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
-            "version": "7.1.0",
-            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
-            "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+        "node_modules/@humanwhocodes/retry": {
+            "version": "0.4.2",
+            "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz",
+            "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==",
             "dev": true,
-            "license": "MIT",
-            "dependencies": {
-                "ansi-regex": "^6.0.1"
-            },
+            "license": "Apache-2.0",
             "engines": {
-                "node": ">=12"
+                "node": ">=18.18"
             },
             "funding": {
-                "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+                "type": "github",
+                "url": "https://github.com/sponsors/nzakas"
             }
         },
-        "node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
-            "version": "8.1.0",
-            "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
-            "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+        "node_modules/@isaacs/cliui": {
+            "version": "8.0.2",
+            "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+            "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
             "dev": true,
-            "license": "MIT",
+            "license": "ISC",
             "dependencies": {
-                "ansi-styles": "^6.1.0",
-                "string-width": "^5.0.1",
-                "strip-ansi": "^7.0.1"
+                "string-width": "^5.1.2",
+                "string-width-cjs": "npm:string-width@^4.2.0",
+                "strip-ansi": "^7.0.1",
+                "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+                "wrap-ansi": "^8.1.0",
+                "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
             },
             "engines": {
                 "node": ">=12"
-            },
-            "funding": {
-                "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
             }
         },
         "node_modules/@nodelib/fs.scandir": {
@@ -889,6 +914,7 @@
             "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
             "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "@nodelib/fs.stat": "2.0.5",
                 "run-parallel": "^1.1.9"
@@ -902,6 +928,7 @@
             "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
             "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": ">= 8"
             }
@@ -911,6 +938,7 @@
             "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
             "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "@nodelib/fs.scandir": "2.1.5",
                 "fastq": "^1.6.0"
@@ -919,121 +947,148 @@
                 "node": ">= 8"
             }
         },
-        "node_modules/@tootallnate/once": {
-            "version": "1.1.2",
-            "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
-            "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
+        "node_modules/@stylistic/eslint-plugin": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-4.1.0.tgz",
+            "integrity": "sha512-bytbL7qiici7yPyEiId0fGPK9kjQbzcPMj2aftPfzTCyJ/CRSKdtI+iVjM0LSGzGxfunflI+MDDU9vyIIeIpoQ==",
             "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "@typescript-eslint/utils": "^8.23.0",
+                "eslint-visitor-keys": "^4.2.0",
+                "espree": "^10.3.0",
+                "estraverse": "^5.3.0",
+                "picomatch": "^4.0.2"
+            },
             "engines": {
-                "node": ">= 6"
+                "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+            },
+            "peerDependencies": {
+                "eslint": ">=9.0.0"
+            }
+        },
+        "node_modules/@stylistic/eslint-plugin-js": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin-js/-/eslint-plugin-js-4.1.0.tgz",
+            "integrity": "sha512-YOe+dChNoR26JVVt+7BjyebsPIQF05OLNmHCXivq8lLZ4ZeVs4+wXaW+pREVboDiAaSRznauAdAU8f+iQouw6Q==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "eslint-visitor-keys": "^4.2.0",
+                "espree": "^10.3.0"
+            },
+            "engines": {
+                "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+            },
+            "peerDependencies": {
+                "eslint": ">=9.0.0"
             }
         },
         "node_modules/@tsconfig/strictest": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/@tsconfig/strictest/-/strictest-2.0.1.tgz",
-            "integrity": "sha512-7JHHCbyCsGUxLd0pDbp24yz3zjxw2t673W5oAP6HCEdr/UUhaRhYd3SSnUsGCk+VnPVJVA4mXROzbhI+nyIk+w==",
-            "dev": true
+            "version": "2.0.5",
+            "resolved": "https://registry.npmjs.org/@tsconfig/strictest/-/strictest-2.0.5.tgz",
+            "integrity": "sha512-ec4tjL2Rr0pkZ5hww65c+EEPYwxOi4Ryv+0MtjeaSQRJyq322Q27eOQiFbuNgw2hpL4hB1/W/HBGk3VKS43osg==",
+            "dev": true,
+            "license": "MIT"
+        },
+        "node_modules/@types/estree": {
+            "version": "1.0.6",
+            "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
+            "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/@types/json-schema": {
-            "version": "7.0.12",
-            "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz",
-            "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==",
-            "dev": true
+            "version": "7.0.15",
+            "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+            "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/@types/node": {
-            "version": "16.11.68",
-            "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.68.tgz",
-            "integrity": "sha512-JkRpuVz3xCNCWaeQ5EHLR/6woMbHZz/jZ7Kmc63AkU+1HxnoUugzSWMck7dsR4DvNYX8jp9wTi9K7WvnxOIQZQ==",
-            "dev": true
-        },
-        "node_modules/@types/semver": {
-            "version": "7.5.0",
-            "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz",
-            "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==",
-            "dev": true
+            "version": "22.13.5",
+            "resolved": "https://registry.npmjs.org/@types/node/-/node-22.13.5.tgz",
+            "integrity": "sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "undici-types": "~6.20.0"
+            }
         },
         "node_modules/@types/vscode": {
-            "version": "1.83.3",
-            "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.83.3.tgz",
-            "integrity": "sha512-ZPp5+OQNYrCSFoT4jWOZKdcuXijj+JdN2BJNDhWH4pPbVL6PRQycG9NT8C4a94oul1tFMbkVbXXa9HasI7cLUg==",
-            "dev": true
+            "version": "1.93.0",
+            "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.93.0.tgz",
+            "integrity": "sha512-kUK6jAHSR5zY8ps42xuW89NLcBpw1kOabah7yv38J8MyiYuOHxLQBi0e7zeXbQgVefDy/mZZetqEFC+Fl5eIEQ==",
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/@typescript-eslint/eslint-plugin": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.0.0.tgz",
-            "integrity": "sha512-xuv6ghKGoiq856Bww/yVYnXGsKa588kY3M0XK7uUW/3fJNNULKRfZfSBkMTSpqGG/8ZCXCadfh8G/z/B4aqS/A==",
+            "version": "8.25.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.25.0.tgz",
+            "integrity": "sha512-VM7bpzAe7JO/BFf40pIT1lJqS/z1F8OaSsUB3rpFJucQA4cOSuH2RVVVkFULN+En0Djgr29/jb4EQnedUo95KA==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "@eslint-community/regexpp": "^4.5.0",
-                "@typescript-eslint/scope-manager": "6.0.0",
-                "@typescript-eslint/type-utils": "6.0.0",
-                "@typescript-eslint/utils": "6.0.0",
-                "@typescript-eslint/visitor-keys": "6.0.0",
-                "debug": "^4.3.4",
-                "grapheme-splitter": "^1.0.4",
+                "@eslint-community/regexpp": "^4.10.0",
+                "@typescript-eslint/scope-manager": "8.25.0",
+                "@typescript-eslint/type-utils": "8.25.0",
+                "@typescript-eslint/utils": "8.25.0",
+                "@typescript-eslint/visitor-keys": "8.25.0",
                 "graphemer": "^1.4.0",
-                "ignore": "^5.2.4",
+                "ignore": "^5.3.1",
                 "natural-compare": "^1.4.0",
-                "natural-compare-lite": "^1.4.0",
-                "semver": "^7.5.0",
-                "ts-api-utils": "^1.0.1"
+                "ts-api-utils": "^2.0.1"
             },
             "engines": {
-                "node": "^16.0.0 || >=18.0.0"
+                "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
             },
             "funding": {
                 "type": "opencollective",
                 "url": "https://opencollective.com/typescript-eslint"
             },
             "peerDependencies": {
-                "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha",
-                "eslint": "^7.0.0 || ^8.0.0"
-            },
-            "peerDependenciesMeta": {
-                "typescript": {
-                    "optional": true
-                }
+                "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0",
+                "eslint": "^8.57.0 || ^9.0.0",
+                "typescript": ">=4.8.4 <5.8.0"
             }
         },
         "node_modules/@typescript-eslint/parser": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.0.0.tgz",
-            "integrity": "sha512-TNaufYSPrr1U8n+3xN+Yp9g31vQDJqhXzzPSHfQDLcaO4tU+mCfODPxCwf4H530zo7aUBE3QIdxCXamEnG04Tg==",
+            "version": "8.25.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.25.0.tgz",
+            "integrity": "sha512-4gbs64bnbSzu4FpgMiQ1A+D+urxkoJk/kqlDJ2W//5SygaEiAP2B4GoS7TEdxgwol2el03gckFV9lJ4QOMiiHg==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "@typescript-eslint/scope-manager": "6.0.0",
-                "@typescript-eslint/types": "6.0.0",
-                "@typescript-eslint/typescript-estree": "6.0.0",
-                "@typescript-eslint/visitor-keys": "6.0.0",
+                "@typescript-eslint/scope-manager": "8.25.0",
+                "@typescript-eslint/types": "8.25.0",
+                "@typescript-eslint/typescript-estree": "8.25.0",
+                "@typescript-eslint/visitor-keys": "8.25.0",
                 "debug": "^4.3.4"
             },
             "engines": {
-                "node": "^16.0.0 || >=18.0.0"
+                "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
             },
             "funding": {
                 "type": "opencollective",
                 "url": "https://opencollective.com/typescript-eslint"
             },
             "peerDependencies": {
-                "eslint": "^7.0.0 || ^8.0.0"
-            },
-            "peerDependenciesMeta": {
-                "typescript": {
-                    "optional": true
-                }
+                "eslint": "^8.57.0 || ^9.0.0",
+                "typescript": ">=4.8.4 <5.8.0"
             }
         },
         "node_modules/@typescript-eslint/scope-manager": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.0.0.tgz",
-            "integrity": "sha512-o4q0KHlgCZTqjuaZ25nw5W57NeykZT9LiMEG4do/ovwvOcPnDO1BI5BQdCsUkjxFyrCL0cSzLjvIMfR9uo7cWg==",
+            "version": "8.25.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.25.0.tgz",
+            "integrity": "sha512-6PPeiKIGbgStEyt4NNXa2ru5pMzQ8OYKO1hX1z53HMomrmiSB+R5FmChgQAP1ro8jMtNawz+TRQo/cSXrauTpg==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "@typescript-eslint/types": "6.0.0",
-                "@typescript-eslint/visitor-keys": "6.0.0"
+                "@typescript-eslint/types": "8.25.0",
+                "@typescript-eslint/visitor-keys": "8.25.0"
             },
             "engines": {
-                "node": "^16.0.0 || >=18.0.0"
+                "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
             },
             "funding": {
                 "type": "opencollective",
@@ -1041,39 +1096,37 @@
             }
         },
         "node_modules/@typescript-eslint/type-utils": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.0.0.tgz",
-            "integrity": "sha512-ah6LJvLgkoZ/pyJ9GAdFkzeuMZ8goV6BH7eC9FPmojrnX9yNCIsfjB+zYcnex28YO3RFvBkV6rMV6WpIqkPvoQ==",
+            "version": "8.25.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.25.0.tgz",
+            "integrity": "sha512-d77dHgHWnxmXOPJuDWO4FDWADmGQkN5+tt6SFRZz/RtCWl4pHgFl3+WdYCn16+3teG09DY6XtEpf3gGD0a186g==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "@typescript-eslint/typescript-estree": "6.0.0",
-                "@typescript-eslint/utils": "6.0.0",
+                "@typescript-eslint/typescript-estree": "8.25.0",
+                "@typescript-eslint/utils": "8.25.0",
                 "debug": "^4.3.4",
-                "ts-api-utils": "^1.0.1"
+                "ts-api-utils": "^2.0.1"
             },
             "engines": {
-                "node": "^16.0.0 || >=18.0.0"
+                "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
             },
             "funding": {
                 "type": "opencollective",
                 "url": "https://opencollective.com/typescript-eslint"
             },
             "peerDependencies": {
-                "eslint": "^7.0.0 || ^8.0.0"
-            },
-            "peerDependenciesMeta": {
-                "typescript": {
-                    "optional": true
-                }
+                "eslint": "^8.57.0 || ^9.0.0",
+                "typescript": ">=4.8.4 <5.8.0"
             }
         },
         "node_modules/@typescript-eslint/types": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.0.0.tgz",
-            "integrity": "sha512-Zk9KDggyZM6tj0AJWYYKgF0yQyrcnievdhG0g5FqyU3Y2DRxJn4yWY21sJC0QKBckbsdKKjYDV2yVrrEvuTgxg==",
+            "version": "8.25.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.25.0.tgz",
+            "integrity": "sha512-+vUe0Zb4tkNgznQwicsvLUJgZIRs6ITeWSCclX1q85pR1iOiaj+4uZJIUp//Z27QWu5Cseiw3O3AR8hVpax7Aw==",
             "dev": true,
+            "license": "MIT",
             "engines": {
-                "node": "^16.0.0 || >=18.0.0"
+                "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
             },
             "funding": {
                 "type": "opencollective",
@@ -1081,69 +1134,68 @@
             }
         },
         "node_modules/@typescript-eslint/typescript-estree": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.0.0.tgz",
-            "integrity": "sha512-2zq4O7P6YCQADfmJ5OTDQTP3ktajnXIRrYAtHM9ofto/CJZV3QfJ89GEaM2BNGeSr1KgmBuLhEkz5FBkS2RQhQ==",
+            "version": "8.25.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.25.0.tgz",
+            "integrity": "sha512-ZPaiAKEZ6Blt/TPAx5Ot0EIB/yGtLI2EsGoY6F7XKklfMxYQyvtL+gT/UCqkMzO0BVFHLDlzvFqQzurYahxv9Q==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "@typescript-eslint/types": "6.0.0",
-                "@typescript-eslint/visitor-keys": "6.0.0",
+                "@typescript-eslint/types": "8.25.0",
+                "@typescript-eslint/visitor-keys": "8.25.0",
                 "debug": "^4.3.4",
-                "globby": "^11.1.0",
+                "fast-glob": "^3.3.2",
                 "is-glob": "^4.0.3",
-                "semver": "^7.5.0",
-                "ts-api-utils": "^1.0.1"
+                "minimatch": "^9.0.4",
+                "semver": "^7.6.0",
+                "ts-api-utils": "^2.0.1"
             },
             "engines": {
-                "node": "^16.0.0 || >=18.0.0"
+                "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
             },
             "funding": {
                 "type": "opencollective",
                 "url": "https://opencollective.com/typescript-eslint"
             },
-            "peerDependenciesMeta": {
-                "typescript": {
-                    "optional": true
-                }
+            "peerDependencies": {
+                "typescript": ">=4.8.4 <5.8.0"
             }
         },
         "node_modules/@typescript-eslint/utils": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.0.0.tgz",
-            "integrity": "sha512-SOr6l4NB6HE4H/ktz0JVVWNXqCJTOo/mHnvIte1ZhBQ0Cvd04x5uKZa3zT6tiodL06zf5xxdK8COiDvPnQ27JQ==",
+            "version": "8.25.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.25.0.tgz",
+            "integrity": "sha512-syqRbrEv0J1wywiLsK60XzHnQe/kRViI3zwFALrNEgnntn1l24Ra2KvOAWwWbWZ1lBZxZljPDGOq967dsl6fkA==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "@eslint-community/eslint-utils": "^4.3.0",
-                "@types/json-schema": "^7.0.11",
-                "@types/semver": "^7.3.12",
-                "@typescript-eslint/scope-manager": "6.0.0",
-                "@typescript-eslint/types": "6.0.0",
-                "@typescript-eslint/typescript-estree": "6.0.0",
-                "eslint-scope": "^5.1.1",
-                "semver": "^7.5.0"
+                "@eslint-community/eslint-utils": "^4.4.0",
+                "@typescript-eslint/scope-manager": "8.25.0",
+                "@typescript-eslint/types": "8.25.0",
+                "@typescript-eslint/typescript-estree": "8.25.0"
             },
             "engines": {
-                "node": "^16.0.0 || >=18.0.0"
+                "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
             },
             "funding": {
                 "type": "opencollective",
                 "url": "https://opencollective.com/typescript-eslint"
             },
             "peerDependencies": {
-                "eslint": "^7.0.0 || ^8.0.0"
+                "eslint": "^8.57.0 || ^9.0.0",
+                "typescript": ">=4.8.4 <5.8.0"
             }
         },
         "node_modules/@typescript-eslint/visitor-keys": {
-            "version": "6.0.0",
-            "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.0.0.tgz",
-            "integrity": "sha512-cvJ63l8c0yXdeT5POHpL0Q1cZoRcmRKFCtSjNGJxPkcP571EfZMcNbzWAc7oK3D1dRzm/V5EwtkANTZxqvuuUA==",
+            "version": "8.25.0",
+            "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.25.0.tgz",
+            "integrity": "sha512-kCYXKAum9CecGVHGij7muybDfTS2sD3t0L4bJsEZLkyrXUImiCTq1M3LG2SRtOhiHFwMR9wAFplpT6XHYjTkwQ==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "@typescript-eslint/types": "6.0.0",
-                "eslint-visitor-keys": "^3.4.1"
+                "@typescript-eslint/types": "8.25.0",
+                "eslint-visitor-keys": "^4.2.0"
             },
             "engines": {
-                "node": "^16.0.0 || >=18.0.0"
+                "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
             },
             "funding": {
                 "type": "opencollective",
@@ -1151,24 +1203,26 @@
             }
         },
         "node_modules/@vscode/test-electron": {
-            "version": "2.3.8",
-            "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.8.tgz",
-            "integrity": "sha512-b4aZZsBKtMGdDljAsOPObnAi7+VWIaYl3ylCz1jTs+oV6BZ4TNHcVNC3xUn0azPeszBmwSBDQYfFESIaUQnrOg==",
+            "version": "2.4.1",
+            "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.4.1.tgz",
+            "integrity": "sha512-Gc6EdaLANdktQ1t+zozoBVRynfIsMKMc94Svu1QreOBC8y76x4tvaK32TljrLi1LI2+PK58sDVbL7ALdqf3VRQ==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "http-proxy-agent": "^4.0.1",
-                "https-proxy-agent": "^5.0.0",
+                "http-proxy-agent": "^7.0.2",
+                "https-proxy-agent": "^7.0.5",
                 "jszip": "^3.10.1",
-                "semver": "^7.5.2"
+                "ora": "^7.0.1",
+                "semver": "^7.6.2"
             },
             "engines": {
                 "node": ">=16"
             }
         },
         "node_modules/@vscode/vsce": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-3.1.1.tgz",
-            "integrity": "sha512-N62Ca9ElRPLUUzf7l9CeEBlLrYzFPRQq7huKk4pVW+LjIOSXfFIPudixn5QvZcz+yXDOh15IopI3K2o3y9666Q==",
+            "version": "3.2.2",
+            "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-3.2.2.tgz",
+            "integrity": "sha512-4TqdUq/yKlQTHcQMk/DamR632bq/+IJDomSbexOMee/UAYWqYm0XHWA6scGslsCpzY+sCWEhhl0nqdOB0XW1kw==",
             "dev": true,
             "license": "MIT",
             "dependencies": {
@@ -1178,7 +1232,7 @@
                 "chalk": "^2.4.2",
                 "cheerio": "^1.0.0-rc.9",
                 "cockatiel": "^3.1.2",
-                "commander": "^6.2.1",
+                "commander": "^12.1.0",
                 "form-data": "^4.0.0",
                 "glob": "^11.0.0",
                 "hosted-git-info": "^4.0.2",
@@ -1208,9 +1262,9 @@
             }
         },
         "node_modules/@vscode/vsce-sign": {
-            "version": "2.0.4",
-            "resolved": "https://registry.npmjs.org/@vscode/vsce-sign/-/vsce-sign-2.0.4.tgz",
-            "integrity": "sha512-0uL32egStKYfy60IqnynAChMTbL0oqpqk0Ew0YHiIb+fayuGZWADuIPHWUcY1GCnAA+VgchOPDMxnc2R3XGWEA==",
+            "version": "2.0.5",
+            "resolved": "https://registry.npmjs.org/@vscode/vsce-sign/-/vsce-sign-2.0.5.tgz",
+            "integrity": "sha512-GfYWrsT/vypTMDMgWDm75iDmAOMe7F71sZECJ+Ws6/xyIfmB3ELVnVN+LwMFAvmXY+e6eWhR2EzNGF/zAhWY3Q==",
             "dev": true,
             "hasInstallScript": true,
             "license": "SEE LICENSE IN LICENSE.txt",
@@ -1352,141 +1406,36 @@
                 "win32"
             ]
         },
-        "node_modules/@vscode/vsce/node_modules/ansi-styles": {
-            "version": "3.2.1",
-            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-            "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-            "dev": true,
-            "dependencies": {
-                "color-convert": "^1.9.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
         "node_modules/@vscode/vsce/node_modules/brace-expansion": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
-            "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+            "version": "1.1.11",
+            "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+            "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
             "dev": true,
             "license": "MIT",
             "dependencies": {
-                "balanced-match": "^1.0.0"
-            }
-        },
-        "node_modules/@vscode/vsce/node_modules/chalk": {
-            "version": "2.4.2",
-            "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-            "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-            "dev": true,
-            "dependencies": {
-                "ansi-styles": "^3.2.1",
-                "escape-string-regexp": "^1.0.5",
-                "supports-color": "^5.3.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/@vscode/vsce/node_modules/color-convert": {
-            "version": "1.9.3",
-            "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
-            "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
-            "dev": true,
-            "dependencies": {
-                "color-name": "1.1.3"
-            }
-        },
-        "node_modules/@vscode/vsce/node_modules/color-name": {
-            "version": "1.1.3",
-            "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-            "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
-            "dev": true
-        },
-        "node_modules/@vscode/vsce/node_modules/commander": {
-            "version": "6.2.1",
-            "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
-            "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
-            "dev": true,
-            "engines": {
-                "node": ">= 6"
-            }
-        },
-        "node_modules/@vscode/vsce/node_modules/escape-string-regexp": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-            "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
-            "dev": true,
-            "engines": {
-                "node": ">=0.8.0"
-            }
-        },
-        "node_modules/@vscode/vsce/node_modules/glob": {
-            "version": "11.0.0",
-            "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz",
-            "integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==",
-            "dev": true,
-            "license": "ISC",
-            "dependencies": {
-                "foreground-child": "^3.1.0",
-                "jackspeak": "^4.0.1",
-                "minimatch": "^10.0.0",
-                "minipass": "^7.1.2",
-                "package-json-from-dist": "^1.0.0",
-                "path-scurry": "^2.0.0"
-            },
-            "bin": {
-                "glob": "dist/esm/bin.mjs"
-            },
-            "engines": {
-                "node": "20 || >=22"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/isaacs"
+                "balanced-match": "^1.0.0",
+                "concat-map": "0.0.1"
             }
         },
-        "node_modules/@vscode/vsce/node_modules/glob/node_modules/minimatch": {
-            "version": "10.0.1",
-            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
-            "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
+        "node_modules/@vscode/vsce/node_modules/minimatch": {
+            "version": "3.1.2",
+            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+            "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
             "dev": true,
             "license": "ISC",
             "dependencies": {
-                "brace-expansion": "^2.0.1"
-            },
-            "engines": {
-                "node": "20 || >=22"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/isaacs"
-            }
-        },
-        "node_modules/@vscode/vsce/node_modules/has-flag": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-            "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
-            "dev": true,
-            "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/@vscode/vsce/node_modules/supports-color": {
-            "version": "5.5.0",
-            "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-            "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-            "dev": true,
-            "dependencies": {
-                "has-flag": "^3.0.0"
+                "brace-expansion": "^1.1.7"
             },
             "engines": {
-                "node": ">=4"
+                "node": "*"
             }
         },
         "node_modules/acorn": {
-            "version": "8.10.0",
-            "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz",
-            "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==",
+            "version": "8.14.0",
+            "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
+            "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
             "dev": true,
+            "license": "MIT",
             "bin": {
                 "acorn": "bin/acorn"
             },
@@ -1499,20 +1448,19 @@
             "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
             "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
             "dev": true,
+            "license": "MIT",
             "peerDependencies": {
                 "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
             }
         },
         "node_modules/agent-base": {
-            "version": "6.0.2",
-            "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
-            "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+            "version": "7.1.3",
+            "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz",
+            "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==",
             "dev": true,
-            "dependencies": {
-                "debug": "4"
-            },
+            "license": "MIT",
             "engines": {
-                "node": ">= 6.0.0"
+                "node": ">= 14"
             }
         },
         "node_modules/ajv": {
@@ -1520,6 +1468,7 @@
             "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
             "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "fast-deep-equal": "^3.1.1",
                 "fast-json-stable-stringify": "^2.0.0",
@@ -1532,46 +1481,43 @@
             }
         },
         "node_modules/anser": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/anser/-/anser-2.1.1.tgz",
-            "integrity": "sha512-nqLm4HxOTpeLOxcmB3QWmV5TcDFhW9y/fyQ+hivtDFcK4OQ+pQ5fzPnXHM1Mfcm0VkLtvVi1TCPr++Qy0Q/3EQ=="
+            "version": "2.3.2",
+            "resolved": "https://registry.npmjs.org/anser/-/anser-2.3.2.tgz",
+            "integrity": "sha512-PMqBCBvrOVDRqLGooQb+z+t1Q0PiPyurUQeZRR5uHBOVZcW8B04KMmnT12USnhpNX2wCPagWzLVppQMUG3u0Dw==",
+            "license": "MIT"
         },
         "node_modules/ansi-regex": {
-            "version": "5.0.1",
-            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+            "version": "6.1.0",
+            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+            "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+            "dev": true,
+            "license": "MIT",
             "engines": {
-                "node": ">=8"
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/ansi-regex?sponsor=1"
             }
         },
         "node_modules/ansi-styles": {
-            "version": "4.3.0",
-            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-            "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+            "version": "3.2.1",
+            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+            "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+            "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "color-convert": "^2.0.1"
+                "color-convert": "^1.9.0"
             },
             "engines": {
-                "node": ">=8"
-            },
-            "funding": {
-                "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+                "node": ">=4"
             }
         },
         "node_modules/argparse": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
             "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
-            "dev": true
-        },
-        "node_modules/array-union": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
-            "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
             "dev": true,
-            "engines": {
-                "node": ">=8"
-            }
+            "license": "Python-2.0"
         },
         "node_modules/asynckit": {
             "version": "0.4.0",
@@ -1594,7 +1540,8 @@
         "node_modules/balanced-match": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
-            "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+            "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+            "license": "MIT"
         },
         "node_modules/base64-js": {
             "version": "1.5.1",
@@ -1615,26 +1562,26 @@
                     "url": "https://feross.org/support"
                 }
             ],
-            "optional": true
+            "license": "MIT"
         },
         "node_modules/bl": {
-            "version": "4.1.0",
-            "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
-            "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+            "version": "5.1.0",
+            "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz",
+            "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==",
             "dev": true,
-            "optional": true,
+            "license": "MIT",
             "dependencies": {
-                "buffer": "^5.5.0",
+                "buffer": "^6.0.3",
                 "inherits": "^2.0.4",
                 "readable-stream": "^3.4.0"
             }
         },
         "node_modules/bl/node_modules/readable-stream": {
-            "version": "3.6.0",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
-            "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+            "version": "3.6.2",
+            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+            "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
             "dev": true,
-            "optional": true,
+            "license": "MIT",
             "dependencies": {
                 "inherits": "^2.0.3",
                 "string_decoder": "^1.1.1",
@@ -1648,16 +1595,16 @@
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
             "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
-            "dev": true
+            "dev": true,
+            "license": "ISC"
         },
         "node_modules/brace-expansion": {
-            "version": "1.1.11",
-            "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
-            "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
-            "dev": true,
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+            "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+            "license": "MIT",
             "dependencies": {
-                "balanced-match": "^1.0.0",
-                "concat-map": "0.0.1"
+                "balanced-match": "^1.0.0"
             }
         },
         "node_modules/braces": {
@@ -1665,6 +1612,7 @@
             "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
             "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "fill-range": "^7.1.1"
             },
@@ -1673,9 +1621,9 @@
             }
         },
         "node_modules/buffer": {
-            "version": "5.7.1",
-            "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
-            "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+            "version": "6.0.3",
+            "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+            "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
             "dev": true,
             "funding": [
                 {
@@ -1691,10 +1639,10 @@
                     "url": "https://feross.org/support"
                 }
             ],
-            "optional": true,
+            "license": "MIT",
             "dependencies": {
                 "base64-js": "^1.3.1",
-                "ieee754": "^1.1.13"
+                "ieee754": "^1.2.1"
             }
         },
         "node_modules/buffer-crc32": {
@@ -1702,6 +1650,7 @@
             "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
             "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": "*"
             }
@@ -1713,18 +1662,45 @@
             "dev": true,
             "license": "BSD-3-Clause"
         },
-        "node_modules/call-bind": {
-            "version": "1.0.7",
-            "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
-            "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
+        "node_modules/bundle-name": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz",
+            "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "run-applescript": "^7.0.0"
+            },
+            "engines": {
+                "node": ">=18"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/call-bind-apply-helpers": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+            "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
             "dev": true,
             "license": "MIT",
             "dependencies": {
-                "es-define-property": "^1.0.0",
                 "es-errors": "^1.3.0",
-                "function-bind": "^1.1.2",
-                "get-intrinsic": "^1.2.4",
-                "set-function-length": "^1.2.1"
+                "function-bind": "^1.1.2"
+            },
+            "engines": {
+                "node": ">= 0.4"
+            }
+        },
+        "node_modules/call-bound": {
+            "version": "1.0.3",
+            "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz",
+            "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "call-bind-apply-helpers": "^1.0.1",
+                "get-intrinsic": "^1.2.6"
             },
             "engines": {
                 "node": ">= 0.4"
@@ -1738,42 +1714,47 @@
             "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
             "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": ">=6"
             }
         },
         "node_modules/chalk": {
-            "version": "4.1.2",
-            "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-            "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+            "version": "2.4.2",
+            "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+            "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "ansi-styles": "^4.1.0",
-                "supports-color": "^7.1.0"
+                "ansi-styles": "^3.2.1",
+                "escape-string-regexp": "^1.0.5",
+                "supports-color": "^5.3.0"
             },
             "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/chalk/chalk?sponsor=1"
+                "node": ">=4"
             }
         },
         "node_modules/cheerio": {
-            "version": "1.0.0-rc.12",
-            "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz",
-            "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==",
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0.tgz",
+            "integrity": "sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "cheerio-select": "^2.1.0",
                 "dom-serializer": "^2.0.0",
                 "domhandler": "^5.0.3",
-                "domutils": "^3.0.1",
-                "htmlparser2": "^8.0.1",
-                "parse5": "^7.0.0",
-                "parse5-htmlparser2-tree-adapter": "^7.0.0"
+                "domutils": "^3.1.0",
+                "encoding-sniffer": "^0.2.0",
+                "htmlparser2": "^9.1.0",
+                "parse5": "^7.1.2",
+                "parse5-htmlparser2-tree-adapter": "^7.0.0",
+                "parse5-parser-stream": "^7.1.2",
+                "undici": "^6.19.5",
+                "whatwg-mimetype": "^4.0.0"
             },
             "engines": {
-                "node": ">= 6"
+                "node": ">=18.17"
             },
             "funding": {
                 "url": "https://github.com/cheeriojs/cheerio?sponsor=1"
@@ -1784,6 +1765,7 @@
             "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
             "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
             "dev": true,
+            "license": "BSD-2-Clause",
             "dependencies": {
                 "boolbase": "^1.0.0",
                 "css-select": "^5.1.0",
@@ -1801,18 +1783,50 @@
             "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
             "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
             "dev": true,
+            "license": "ISC",
             "optional": true
         },
         "node_modules/ci-info": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
             "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
-            "dev": true
+            "dev": true,
+            "license": "MIT"
+        },
+        "node_modules/cli-cursor": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz",
+            "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "restore-cursor": "^4.0.0"
+            },
+            "engines": {
+                "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/cli-spinners": {
+            "version": "2.9.2",
+            "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz",
+            "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=6"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
         },
         "node_modules/cliui": {
             "version": "8.0.1",
             "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
             "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+            "license": "ISC",
             "dependencies": {
                 "string-width": "^4.2.0",
                 "strip-ansi": "^6.0.1",
@@ -1822,20 +1836,35 @@
                 "node": ">=12"
             }
         },
-        "node_modules/cockatiel": {
-            "version": "3.2.1",
-            "resolved": "https://registry.npmjs.org/cockatiel/-/cockatiel-3.2.1.tgz",
-            "integrity": "sha512-gfrHV6ZPkquExvMh9IOkKsBzNDk6sDuZ6DdBGUBkvFnTCqCxzpuq48RySgP0AnaqQkw2zynOFj9yly6T1Q2G5Q==",
-            "dev": true,
+        "node_modules/cliui/node_modules/ansi-regex": {
+            "version": "5.0.1",
+            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
             "license": "MIT",
             "engines": {
-                "node": ">=16"
+                "node": ">=8"
             }
         },
-        "node_modules/color-convert": {
+        "node_modules/cliui/node_modules/ansi-styles": {
+            "version": "4.3.0",
+            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+            "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+            "license": "MIT",
+            "dependencies": {
+                "color-convert": "^2.0.1"
+            },
+            "engines": {
+                "node": ">=8"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+            }
+        },
+        "node_modules/cliui/node_modules/color-convert": {
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
             "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+            "license": "MIT",
             "dependencies": {
                 "color-name": "~1.1.4"
             },
@@ -1843,10 +1872,87 @@
                 "node": ">=7.0.0"
             }
         },
-        "node_modules/color-name": {
+        "node_modules/cliui/node_modules/color-name": {
             "version": "1.1.4",
             "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-            "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+            "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+            "license": "MIT"
+        },
+        "node_modules/cliui/node_modules/emoji-regex": {
+            "version": "8.0.0",
+            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+            "license": "MIT"
+        },
+        "node_modules/cliui/node_modules/string-width": {
+            "version": "4.2.3",
+            "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+            "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+            "license": "MIT",
+            "dependencies": {
+                "emoji-regex": "^8.0.0",
+                "is-fullwidth-code-point": "^3.0.0",
+                "strip-ansi": "^6.0.1"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/cliui/node_modules/strip-ansi": {
+            "version": "6.0.1",
+            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+            "license": "MIT",
+            "dependencies": {
+                "ansi-regex": "^5.0.1"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/cliui/node_modules/wrap-ansi": {
+            "version": "7.0.0",
+            "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+            "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+            "license": "MIT",
+            "dependencies": {
+                "ansi-styles": "^4.0.0",
+                "string-width": "^4.1.0",
+                "strip-ansi": "^6.0.0"
+            },
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+            }
+        },
+        "node_modules/cockatiel": {
+            "version": "3.2.1",
+            "resolved": "https://registry.npmjs.org/cockatiel/-/cockatiel-3.2.1.tgz",
+            "integrity": "sha512-gfrHV6ZPkquExvMh9IOkKsBzNDk6sDuZ6DdBGUBkvFnTCqCxzpuq48RySgP0AnaqQkw2zynOFj9yly6T1Q2G5Q==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=16"
+            }
+        },
+        "node_modules/color-convert": {
+            "version": "1.9.3",
+            "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+            "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "color-name": "1.1.3"
+            }
+        },
+        "node_modules/color-name": {
+            "version": "1.1.3",
+            "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+            "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/combined-stream": {
             "version": "1.0.8",
@@ -1862,30 +1968,35 @@
             }
         },
         "node_modules/commander": {
-            "version": "7.2.0",
-            "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
-            "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
+            "version": "12.1.0",
+            "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
+            "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
+            "dev": true,
+            "license": "MIT",
             "engines": {
-                "node": ">= 10"
+                "node": ">=18"
             }
         },
         "node_modules/concat-map": {
             "version": "0.0.1",
             "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
             "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
-            "dev": true
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/core-util-is": {
             "version": "1.0.3",
             "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
             "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
-            "dev": true
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/cross-spawn": {
-            "version": "7.0.3",
-            "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
-            "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+            "version": "7.0.6",
+            "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+            "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "path-key": "^3.1.0",
                 "shebang-command": "^2.0.0",
@@ -1900,6 +2011,7 @@
             "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
             "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
             "dev": true,
+            "license": "BSD-2-Clause",
             "dependencies": {
                 "boolbase": "^1.0.0",
                 "css-what": "^6.1.0",
@@ -1916,6 +2028,7 @@
             "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
             "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
             "dev": true,
+            "license": "BSD-2-Clause",
             "engines": {
                 "node": ">= 6"
             },
@@ -1924,9 +2037,10 @@
             }
         },
         "node_modules/d3": {
-            "version": "7.8.5",
-            "resolved": "https://registry.npmjs.org/d3/-/d3-7.8.5.tgz",
-            "integrity": "sha512-JgoahDG51ncUfJu6wX/1vWQEqOflgXyl4MaHqlcSruTez7yhaRKR9i8VjjcQGeS2en/jnFivXuaIMnseMMt0XA==",
+            "version": "7.9.0",
+            "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz",
+            "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==",
+            "license": "ISC",
             "dependencies": {
                 "d3-array": "3",
                 "d3-axis": "3",
@@ -1964,9 +2078,10 @@
             }
         },
         "node_modules/d3-array": {
-            "version": "3.2.2",
-            "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.2.tgz",
-            "integrity": "sha512-yEEyEAbDrF8C6Ob2myOBLjwBLck1Z89jMGFee0oPsn95GqjerpaOA4ch+vc2l0FNFFwMD5N7OCSEN5eAlsUbgQ==",
+            "version": "3.2.4",
+            "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
+            "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
+            "license": "ISC",
             "dependencies": {
                 "internmap": "1 - 2"
             },
@@ -1978,6 +2093,7 @@
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz",
             "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==",
+            "license": "ISC",
             "engines": {
                 "node": ">=12"
             }
@@ -1986,6 +2102,7 @@
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz",
             "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==",
+            "license": "ISC",
             "dependencies": {
                 "d3-dispatch": "1 - 3",
                 "d3-drag": "2 - 3",
@@ -2001,6 +2118,7 @@
             "version": "3.0.1",
             "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz",
             "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==",
+            "license": "ISC",
             "dependencies": {
                 "d3-path": "1 - 3"
             },
@@ -2012,6 +2130,7 @@
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
             "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
+            "license": "ISC",
             "engines": {
                 "node": ">=12"
             }
@@ -2020,6 +2139,7 @@
             "version": "4.0.2",
             "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz",
             "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==",
+            "license": "ISC",
             "dependencies": {
                 "d3-array": "^3.2.0"
             },
@@ -2028,9 +2148,10 @@
             }
         },
         "node_modules/d3-delaunay": {
-            "version": "6.0.2",
-            "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.2.tgz",
-            "integrity": "sha512-IMLNldruDQScrcfT+MWnazhHbDJhcRJyOEBAJfwQnHle1RPh6WDuLvxNArUju2VSMSUuKlY5BGHRJ2cYyoFLQQ==",
+            "version": "6.0.4",
+            "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz",
+            "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==",
+            "license": "ISC",
             "dependencies": {
                 "delaunator": "5"
             },
@@ -2042,6 +2163,7 @@
             "version": "3.0.1",
             "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz",
             "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==",
+            "license": "ISC",
             "engines": {
                 "node": ">=12"
             }
@@ -2050,6 +2172,7 @@
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz",
             "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==",
+            "license": "ISC",
             "dependencies": {
                 "d3-dispatch": "1 - 3",
                 "d3-selection": "3"
@@ -2062,6 +2185,7 @@
             "version": "3.0.1",
             "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz",
             "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==",
+            "license": "ISC",
             "dependencies": {
                 "commander": "7",
                 "iconv-lite": "0.6",
@@ -2082,10 +2206,20 @@
                 "node": ">=12"
             }
         },
+        "node_modules/d3-dsv/node_modules/commander": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+            "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
+            "license": "MIT",
+            "engines": {
+                "node": ">= 10"
+            }
+        },
         "node_modules/d3-ease": {
             "version": "3.0.1",
             "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
             "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
+            "license": "BSD-3-Clause",
             "engines": {
                 "node": ">=12"
             }
@@ -2094,6 +2228,7 @@
             "version": "3.0.1",
             "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz",
             "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==",
+            "license": "ISC",
             "dependencies": {
                 "d3-dsv": "1 - 3"
             },
@@ -2105,6 +2240,7 @@
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz",
             "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==",
+            "license": "ISC",
             "dependencies": {
                 "d3-dispatch": "1 - 3",
                 "d3-quadtree": "1 - 3",
@@ -2118,14 +2254,16 @@
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz",
             "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==",
+            "license": "ISC",
             "engines": {
                 "node": ">=12"
             }
         },
         "node_modules/d3-geo": {
-            "version": "3.1.0",
-            "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.0.tgz",
-            "integrity": "sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==",
+            "version": "3.1.1",
+            "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz",
+            "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==",
+            "license": "ISC",
             "dependencies": {
                 "d3-array": "2.5.0 - 3"
             },
@@ -2134,11 +2272,12 @@
             }
         },
         "node_modules/d3-graphviz": {
-            "version": "5.0.2",
-            "resolved": "https://registry.npmjs.org/d3-graphviz/-/d3-graphviz-5.0.2.tgz",
-            "integrity": "sha512-EVRow9rnFgm/L1trbbnu2PGOND11IcSEdWXbrDbz9hH0/Kj3YM2AqMkkTN/EAWgawD5/zryyCy+3Vm05oSJ1Kg==",
+            "version": "5.6.0",
+            "resolved": "https://registry.npmjs.org/d3-graphviz/-/d3-graphviz-5.6.0.tgz",
+            "integrity": "sha512-46OOyRv5Ioo9kZBc919FVIYPD/ObtdSZxOK1hv+qwmD7TunpPvvmsI1dSdxhVgH4GragJxFZ31+TQC5aOuXzzw==",
+            "license": "BSD-3-Clause",
             "dependencies": {
-                "@hpcc-js/wasm": "2.5.0",
+                "@hpcc-js/wasm": "^2.20.0",
                 "d3-dispatch": "^3.0.1",
                 "d3-format": "^3.1.0",
                 "d3-interpolate": "^3.0.1",
@@ -2154,38 +2293,11 @@
                 "d3-selection": "^3.0.0"
             }
         },
-        "node_modules/d3-graphviz/node_modules/@hpcc-js/wasm": {
-            "version": "2.5.0",
-            "resolved": "https://registry.npmjs.org/@hpcc-js/wasm/-/wasm-2.5.0.tgz",
-            "integrity": "sha512-G26BamgaHW46f6P8bmkygapgNcy+tTDMwIvCzmMzdp39sxUS1u4gaT/vR2SSDc4x3SfL5RE4B2B8ef/wd429Hg==",
-            "dependencies": {
-                "yargs": "17.6.2"
-            },
-            "bin": {
-                "dot-wasm": "bin/dot-wasm.js"
-            }
-        },
-        "node_modules/d3-graphviz/node_modules/yargs": {
-            "version": "17.6.2",
-            "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz",
-            "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==",
-            "dependencies": {
-                "cliui": "^8.0.1",
-                "escalade": "^3.1.1",
-                "get-caller-file": "^2.0.5",
-                "require-directory": "^2.1.1",
-                "string-width": "^4.2.3",
-                "y18n": "^5.0.5",
-                "yargs-parser": "^21.1.1"
-            },
-            "engines": {
-                "node": ">=12"
-            }
-        },
         "node_modules/d3-hierarchy": {
             "version": "3.1.2",
             "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz",
             "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==",
+            "license": "ISC",
             "engines": {
                 "node": ">=12"
             }
@@ -2194,6 +2306,7 @@
             "version": "3.0.1",
             "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
             "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
+            "license": "ISC",
             "dependencies": {
                 "d3-color": "1 - 3"
             },
@@ -2205,6 +2318,7 @@
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz",
             "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==",
+            "license": "ISC",
             "engines": {
                 "node": ">=12"
             }
@@ -2213,6 +2327,7 @@
             "version": "3.0.1",
             "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz",
             "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==",
+            "license": "ISC",
             "engines": {
                 "node": ">=12"
             }
@@ -2221,6 +2336,7 @@
             "version": "3.0.1",
             "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz",
             "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==",
+            "license": "ISC",
             "engines": {
                 "node": ">=12"
             }
@@ -2229,6 +2345,7 @@
             "version": "3.0.1",
             "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz",
             "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==",
+            "license": "ISC",
             "engines": {
                 "node": ">=12"
             }
@@ -2237,6 +2354,7 @@
             "version": "4.0.2",
             "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
             "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
+            "license": "ISC",
             "dependencies": {
                 "d3-array": "2.10.0 - 3",
                 "d3-format": "1 - 3",
@@ -2249,9 +2367,10 @@
             }
         },
         "node_modules/d3-scale-chromatic": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz",
-            "integrity": "sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==",
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz",
+            "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==",
+            "license": "ISC",
             "dependencies": {
                 "d3-color": "1 - 3",
                 "d3-interpolate": "1 - 3"
@@ -2264,6 +2383,7 @@
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
             "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
+            "license": "ISC",
             "engines": {
                 "node": ">=12"
             }
@@ -2272,6 +2392,7 @@
             "version": "3.2.0",
             "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz",
             "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
+            "license": "ISC",
             "dependencies": {
                 "d3-path": "^3.1.0"
             },
@@ -2283,6 +2404,7 @@
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
             "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
+            "license": "ISC",
             "dependencies": {
                 "d3-array": "2 - 3"
             },
@@ -2294,6 +2416,7 @@
             "version": "4.1.0",
             "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz",
             "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
+            "license": "ISC",
             "dependencies": {
                 "d3-time": "1 - 3"
             },
@@ -2305,6 +2428,7 @@
             "version": "3.0.1",
             "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
             "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
+            "license": "ISC",
             "engines": {
                 "node": ">=12"
             }
@@ -2313,6 +2437,7 @@
             "version": "3.0.1",
             "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz",
             "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==",
+            "license": "ISC",
             "dependencies": {
                 "d3-color": "1 - 3",
                 "d3-dispatch": "1 - 3",
@@ -2331,6 +2456,7 @@
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz",
             "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==",
+            "license": "ISC",
             "dependencies": {
                 "d3-dispatch": "1 - 3",
                 "d3-drag": "2 - 3",
@@ -2343,12 +2469,13 @@
             }
         },
         "node_modules/debug": {
-            "version": "4.3.4",
-            "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-            "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+            "version": "4.4.0",
+            "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
+            "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "ms": "2.1.2"
+                "ms": "^2.1.3"
             },
             "engines": {
                 "node": ">=6.0"
@@ -2364,6 +2491,7 @@
             "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
             "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
             "dev": true,
+            "license": "MIT",
             "optional": true,
             "dependencies": {
                 "mimic-response": "^3.1.0"
@@ -2380,6 +2508,7 @@
             "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
             "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
             "dev": true,
+            "license": "MIT",
             "optional": true,
             "engines": {
                 "node": ">=4.0.0"
@@ -2389,42 +2518,59 @@
             "version": "0.1.4",
             "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
             "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
-            "dev": true
+            "dev": true,
+            "license": "MIT"
         },
-        "node_modules/define-data-property": {
-            "version": "1.1.4",
-            "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
-            "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+        "node_modules/default-browser": {
+            "version": "5.2.1",
+            "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz",
+            "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==",
             "dev": true,
             "license": "MIT",
             "dependencies": {
-                "es-define-property": "^1.0.0",
-                "es-errors": "^1.3.0",
-                "gopd": "^1.0.1"
+                "bundle-name": "^4.1.0",
+                "default-browser-id": "^5.0.0"
             },
             "engines": {
-                "node": ">= 0.4"
+                "node": ">=18"
             },
             "funding": {
-                "url": "https://github.com/sponsors/ljharb"
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/default-browser-id": {
+            "version": "5.0.0",
+            "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz",
+            "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=18"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
             }
         },
         "node_modules/define-lazy-prop": {
-            "version": "2.0.0",
-            "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
-            "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
+            "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==",
             "dev": true,
             "license": "MIT",
             "engines": {
-                "node": ">=8"
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
             }
         },
         "node_modules/delaunator": {
-            "version": "5.0.0",
-            "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz",
-            "integrity": "sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==",
+            "version": "5.0.1",
+            "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz",
+            "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==",
+            "license": "ISC",
             "dependencies": {
-                "robust-predicates": "^3.0.0"
+                "robust-predicates": "^3.0.2"
             }
         },
         "node_modules/delayed-stream": {
@@ -2438,44 +2584,22 @@
             }
         },
         "node_modules/detect-libc": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz",
-            "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==",
+            "version": "2.0.3",
+            "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
+            "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
             "dev": true,
+            "license": "Apache-2.0",
             "optional": true,
             "engines": {
                 "node": ">=8"
             }
         },
-        "node_modules/dir-glob": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
-            "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
-            "dev": true,
-            "dependencies": {
-                "path-type": "^4.0.0"
-            },
-            "engines": {
-                "node": ">=8"
-            }
-        },
-        "node_modules/doctrine": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
-            "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
-            "dev": true,
-            "dependencies": {
-                "esutils": "^2.0.2"
-            },
-            "engines": {
-                "node": ">=6.0.0"
-            }
-        },
         "node_modules/dom-serializer": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
             "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "domelementtype": "^2.3.0",
                 "domhandler": "^5.0.2",
@@ -2495,13 +2619,15 @@
                     "type": "github",
                     "url": "https://github.com/sponsors/fb55"
                 }
-            ]
+            ],
+            "license": "BSD-2-Clause"
         },
         "node_modules/domhandler": {
             "version": "5.0.3",
             "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
             "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
             "dev": true,
+            "license": "BSD-2-Clause",
             "dependencies": {
                 "domelementtype": "^2.3.0"
             },
@@ -2513,19 +2639,35 @@
             }
         },
         "node_modules/domutils": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz",
-            "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==",
+            "version": "3.2.2",
+            "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
+            "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
             "dev": true,
+            "license": "BSD-2-Clause",
             "dependencies": {
                 "dom-serializer": "^2.0.0",
                 "domelementtype": "^2.3.0",
-                "domhandler": "^5.0.1"
+                "domhandler": "^5.0.3"
             },
             "funding": {
                 "url": "https://github.com/fb55/domutils?sponsor=1"
             }
         },
+        "node_modules/dunder-proto": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+            "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "call-bind-apply-helpers": "^1.0.1",
+                "es-errors": "^1.3.0",
+                "gopd": "^1.2.0"
+            },
+            "engines": {
+                "node": ">= 0.4"
+            }
+        },
         "node_modules/eastasianwidth": {
             "version": "0.2.0",
             "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
@@ -2544,25 +2686,43 @@
             }
         },
         "node_modules/emoji-regex": {
-            "version": "8.0.0",
-            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+            "version": "9.2.2",
+            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+            "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+            "dev": true,
+            "license": "MIT"
+        },
+        "node_modules/encoding-sniffer": {
+            "version": "0.2.0",
+            "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.0.tgz",
+            "integrity": "sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "iconv-lite": "^0.6.3",
+                "whatwg-encoding": "^3.1.1"
+            },
+            "funding": {
+                "url": "https://github.com/fb55/encoding-sniffer?sponsor=1"
+            }
         },
         "node_modules/end-of-stream": {
             "version": "1.4.4",
             "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
             "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
             "dev": true,
+            "license": "MIT",
             "optional": true,
             "dependencies": {
                 "once": "^1.4.0"
             }
         },
         "node_modules/entities": {
-            "version": "4.4.0",
-            "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz",
-            "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==",
+            "version": "4.5.0",
+            "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+            "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
             "dev": true,
+            "license": "BSD-2-Clause",
             "engines": {
                 "node": ">=0.12"
             },
@@ -2571,14 +2731,11 @@
             }
         },
         "node_modules/es-define-property": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
-            "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+            "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
             "dev": true,
             "license": "MIT",
-            "dependencies": {
-                "get-intrinsic": "^1.2.4"
-            },
             "engines": {
                 "node": ">= 0.4"
             }
@@ -2593,6 +2750,35 @@
                 "node": ">= 0.4"
             }
         },
+        "node_modules/es-object-atoms": {
+            "version": "1.1.1",
+            "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+            "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "es-errors": "^1.3.0"
+            },
+            "engines": {
+                "node": ">= 0.4"
+            }
+        },
+        "node_modules/es-set-tostringtag": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+            "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "es-errors": "^1.3.0",
+                "get-intrinsic": "^1.2.6",
+                "has-tostringtag": "^1.0.2",
+                "hasown": "^2.0.2"
+            },
+            "engines": {
+                "node": ">= 0.4"
+            }
+        },
         "node_modules/esbuild": {
             "version": "0.25.0",
             "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz",
@@ -2635,165 +2821,286 @@
             }
         },
         "node_modules/escalade": {
-            "version": "3.1.1",
-            "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
-            "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+            "version": "3.2.0",
+            "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+            "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+            "license": "MIT",
             "engines": {
                 "node": ">=6"
             }
         },
         "node_modules/escape-string-regexp": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
-            "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+            "version": "1.0.5",
+            "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+            "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
             "dev": true,
+            "license": "MIT",
             "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
+                "node": ">=0.8.0"
             }
         },
         "node_modules/eslint": {
-            "version": "8.44.0",
-            "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.44.0.tgz",
-            "integrity": "sha512-0wpHoUbDUHgNCyvFB5aXLiQVfK9B0at6gUvzy83k4kAsQ/u769TQDX6iKC+aO4upIHO9WSaA3QoXYQDHbNwf1A==",
+            "version": "9.21.0",
+            "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.21.0.tgz",
+            "integrity": "sha512-KjeihdFqTPhOMXTt7StsDxriV4n66ueuF/jfPNC3j/lduHwr/ijDwJMsF+wyMJethgiKi5wniIE243vi07d3pg==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "@eslint-community/eslint-utils": "^4.2.0",
-                "@eslint-community/regexpp": "^4.4.0",
-                "@eslint/eslintrc": "^2.1.0",
-                "@eslint/js": "8.44.0",
-                "@humanwhocodes/config-array": "^0.11.10",
+                "@eslint-community/regexpp": "^4.12.1",
+                "@eslint/config-array": "^0.19.2",
+                "@eslint/core": "^0.12.0",
+                "@eslint/eslintrc": "^3.3.0",
+                "@eslint/js": "9.21.0",
+                "@eslint/plugin-kit": "^0.2.7",
+                "@humanfs/node": "^0.16.6",
                 "@humanwhocodes/module-importer": "^1.0.1",
-                "@nodelib/fs.walk": "^1.2.8",
-                "ajv": "^6.10.0",
+                "@humanwhocodes/retry": "^0.4.2",
+                "@types/estree": "^1.0.6",
+                "@types/json-schema": "^7.0.15",
+                "ajv": "^6.12.4",
                 "chalk": "^4.0.0",
-                "cross-spawn": "^7.0.2",
+                "cross-spawn": "^7.0.6",
                 "debug": "^4.3.2",
-                "doctrine": "^3.0.0",
                 "escape-string-regexp": "^4.0.0",
-                "eslint-scope": "^7.2.0",
-                "eslint-visitor-keys": "^3.4.1",
-                "espree": "^9.6.0",
-                "esquery": "^1.4.2",
+                "eslint-scope": "^8.2.0",
+                "eslint-visitor-keys": "^4.2.0",
+                "espree": "^10.3.0",
+                "esquery": "^1.5.0",
                 "esutils": "^2.0.2",
                 "fast-deep-equal": "^3.1.3",
-                "file-entry-cache": "^6.0.1",
+                "file-entry-cache": "^8.0.0",
                 "find-up": "^5.0.0",
                 "glob-parent": "^6.0.2",
-                "globals": "^13.19.0",
-                "graphemer": "^1.4.0",
                 "ignore": "^5.2.0",
-                "import-fresh": "^3.0.0",
                 "imurmurhash": "^0.1.4",
                 "is-glob": "^4.0.0",
-                "is-path-inside": "^3.0.3",
-                "js-yaml": "^4.1.0",
                 "json-stable-stringify-without-jsonify": "^1.0.1",
-                "levn": "^0.4.1",
                 "lodash.merge": "^4.6.2",
                 "minimatch": "^3.1.2",
                 "natural-compare": "^1.4.0",
-                "optionator": "^0.9.3",
-                "strip-ansi": "^6.0.1",
-                "strip-json-comments": "^3.1.0",
-                "text-table": "^0.2.0"
+                "optionator": "^0.9.3"
             },
             "bin": {
                 "eslint": "bin/eslint.js"
             },
             "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+                "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
             },
             "funding": {
-                "url": "https://opencollective.com/eslint"
+                "url": "https://eslint.org/donate"
+            },
+            "peerDependencies": {
+                "jiti": "*"
+            },
+            "peerDependenciesMeta": {
+                "jiti": {
+                    "optional": true
+                }
             }
         },
         "node_modules/eslint-config-prettier": {
-            "version": "8.8.0",
-            "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz",
-            "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==",
+            "version": "10.0.2",
+            "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.0.2.tgz",
+            "integrity": "sha512-1105/17ZIMjmCOJOPNfVdbXafLCLj3hPmkmB7dLgt7XsQ/zkxSuDerE/xgO3RxoHysR1N1whmquY0lSn2O0VLg==",
             "dev": true,
+            "license": "MIT",
             "bin": {
-                "eslint-config-prettier": "bin/cli.js"
+                "eslint-config-prettier": "build/bin/cli.js"
             },
             "peerDependencies": {
                 "eslint": ">=7.0.0"
             }
         },
+        "node_modules/eslint-define-config": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/eslint-define-config/-/eslint-define-config-2.1.0.tgz",
+            "integrity": "sha512-QUp6pM9pjKEVannNAbSJNeRuYwW3LshejfyBBpjeMGaJjaDUpVps4C6KVR8R7dWZnD3i0synmrE36znjTkJvdQ==",
+            "dev": true,
+            "funding": [
+                {
+                    "type": "github",
+                    "url": "https://github.com/Shinigami92"
+                },
+                {
+                    "type": "paypal",
+                    "url": "https://www.paypal.com/donate/?hosted_button_id=L7GY729FBKTZY"
+                }
+            ],
+            "license": "MIT",
+            "engines": {
+                "node": ">=18.0.0",
+                "npm": ">=9.0.0",
+                "pnpm": ">=8.6.0"
+            }
+        },
         "node_modules/eslint-scope": {
-            "version": "5.1.1",
-            "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
-            "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+            "version": "8.2.0",
+            "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz",
+            "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==",
             "dev": true,
+            "license": "BSD-2-Clause",
             "dependencies": {
                 "esrecurse": "^4.3.0",
-                "estraverse": "^4.1.1"
+                "estraverse": "^5.2.0"
             },
             "engines": {
-                "node": ">=8.0.0"
+                "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/eslint"
             }
         },
         "node_modules/eslint-visitor-keys": {
-            "version": "3.4.1",
-            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz",
-            "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==",
+            "version": "4.2.0",
+            "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
+            "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
             "dev": true,
+            "license": "Apache-2.0",
             "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+                "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
             },
             "funding": {
                 "url": "https://opencollective.com/eslint"
             }
         },
-        "node_modules/eslint/node_modules/eslint-scope": {
-            "version": "7.2.0",
-            "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz",
-            "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==",
+        "node_modules/eslint/node_modules/ansi-styles": {
+            "version": "4.3.0",
+            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+            "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "esrecurse": "^4.3.0",
-                "estraverse": "^5.2.0"
+                "color-convert": "^2.0.1"
             },
             "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+                "node": ">=8"
             },
             "funding": {
-                "url": "https://opencollective.com/eslint"
+                "url": "https://github.com/chalk/ansi-styles?sponsor=1"
             }
         },
-        "node_modules/eslint/node_modules/estraverse": {
-            "version": "5.3.0",
-            "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
-            "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+        "node_modules/eslint/node_modules/brace-expansion": {
+            "version": "1.1.11",
+            "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+            "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "balanced-match": "^1.0.0",
+                "concat-map": "0.0.1"
+            }
+        },
+        "node_modules/eslint/node_modules/chalk": {
+            "version": "4.1.2",
+            "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+            "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
             "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "ansi-styles": "^4.1.0",
+                "supports-color": "^7.1.0"
+            },
             "engines": {
-                "node": ">=4.0"
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/chalk?sponsor=1"
+            }
+        },
+        "node_modules/eslint/node_modules/color-convert": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+            "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "color-name": "~1.1.4"
+            },
+            "engines": {
+                "node": ">=7.0.0"
+            }
+        },
+        "node_modules/eslint/node_modules/color-name": {
+            "version": "1.1.4",
+            "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+            "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+            "dev": true,
+            "license": "MIT"
+        },
+        "node_modules/eslint/node_modules/escape-string-regexp": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+            "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/eslint/node_modules/has-flag": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+            "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/eslint/node_modules/minimatch": {
+            "version": "3.1.2",
+            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+            "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+            "dev": true,
+            "license": "ISC",
+            "dependencies": {
+                "brace-expansion": "^1.1.7"
+            },
+            "engines": {
+                "node": "*"
+            }
+        },
+        "node_modules/eslint/node_modules/supports-color": {
+            "version": "7.2.0",
+            "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+            "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "has-flag": "^4.0.0"
+            },
+            "engines": {
+                "node": ">=8"
             }
         },
         "node_modules/espree": {
-            "version": "9.6.0",
-            "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.0.tgz",
-            "integrity": "sha512-1FH/IiruXZ84tpUlm0aCUEwMl2Ho5ilqVh0VvQXw+byAz/4SAciyHLlfmL5WYqsvD38oymdUwBss0LtK8m4s/A==",
+            "version": "10.3.0",
+            "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz",
+            "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==",
             "dev": true,
+            "license": "BSD-2-Clause",
             "dependencies": {
-                "acorn": "^8.9.0",
+                "acorn": "^8.14.0",
                 "acorn-jsx": "^5.3.2",
-                "eslint-visitor-keys": "^3.4.1"
+                "eslint-visitor-keys": "^4.2.0"
             },
             "engines": {
-                "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+                "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
             },
             "funding": {
                 "url": "https://opencollective.com/eslint"
             }
         },
         "node_modules/esquery": {
-            "version": "1.5.0",
-            "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
-            "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+            "version": "1.6.0",
+            "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+            "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
             "dev": true,
+            "license": "BSD-3-Clause",
             "dependencies": {
                 "estraverse": "^5.1.0"
             },
@@ -2801,20 +3108,12 @@
                 "node": ">=0.10"
             }
         },
-        "node_modules/esquery/node_modules/estraverse": {
-            "version": "5.3.0",
-            "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
-            "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
-            "dev": true,
-            "engines": {
-                "node": ">=4.0"
-            }
-        },
         "node_modules/esrecurse": {
             "version": "4.3.0",
             "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
             "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
             "dev": true,
+            "license": "BSD-2-Clause",
             "dependencies": {
                 "estraverse": "^5.2.0"
             },
@@ -2822,20 +3121,12 @@
                 "node": ">=4.0"
             }
         },
-        "node_modules/esrecurse/node_modules/estraverse": {
+        "node_modules/estraverse": {
             "version": "5.3.0",
             "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
             "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
             "dev": true,
-            "engines": {
-                "node": ">=4.0"
-            }
-        },
-        "node_modules/estraverse": {
-            "version": "4.3.0",
-            "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
-            "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
-            "dev": true,
+            "license": "BSD-2-Clause",
             "engines": {
                 "node": ">=4.0"
             }
@@ -2845,6 +3136,7 @@
             "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
             "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
             "dev": true,
+            "license": "BSD-2-Clause",
             "engines": {
                 "node": ">=0.10.0"
             }
@@ -2864,6 +3156,7 @@
             "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
             "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
             "dev": true,
+            "license": "(MIT OR WTFPL)",
             "optional": true,
             "engines": {
                 "node": ">=6"
@@ -2873,19 +3166,21 @@
             "version": "3.1.3",
             "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
             "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
-            "dev": true
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/fast-glob": {
-            "version": "3.3.0",
-            "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz",
-            "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==",
+            "version": "3.3.3",
+            "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
+            "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "@nodelib/fs.stat": "^2.0.2",
                 "@nodelib/fs.walk": "^1.2.3",
                 "glob-parent": "^5.1.2",
                 "merge2": "^1.3.0",
-                "micromatch": "^4.0.4"
+                "micromatch": "^4.0.8"
             },
             "engines": {
                 "node": ">=8.6.0"
@@ -2896,6 +3191,7 @@
             "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
             "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
             "dev": true,
+            "license": "ISC",
             "dependencies": {
                 "is-glob": "^4.0.1"
             },
@@ -2907,19 +3203,22 @@
             "version": "2.1.0",
             "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
             "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
-            "dev": true
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/fast-levenshtein": {
             "version": "2.0.6",
             "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
             "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
-            "dev": true
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/fastq": {
-            "version": "1.15.0",
-            "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
-            "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
+            "version": "1.19.0",
+            "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz",
+            "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==",
             "dev": true,
+            "license": "ISC",
             "dependencies": {
                 "reusify": "^1.0.4"
             }
@@ -2929,20 +3228,22 @@
             "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
             "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "pend": "~1.2.0"
             }
         },
         "node_modules/file-entry-cache": {
-            "version": "6.0.1",
-            "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
-            "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+            "version": "8.0.0",
+            "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+            "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "flat-cache": "^3.0.4"
+                "flat-cache": "^4.0.0"
             },
             "engines": {
-                "node": "^10.12.0 || >=12.0.0"
+                "node": ">=16.0.0"
             }
         },
         "node_modules/fill-range": {
@@ -2950,6 +3251,7 @@
             "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
             "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "to-regex-range": "^5.0.1"
             },
@@ -2962,6 +3264,7 @@
             "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
             "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "locate-path": "^6.0.0",
                 "path-exists": "^4.0.0"
@@ -2974,28 +3277,30 @@
             }
         },
         "node_modules/flat-cache": {
-            "version": "3.0.4",
-            "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
-            "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+            "version": "4.0.1",
+            "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+            "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "flatted": "^3.1.0",
-                "rimraf": "^3.0.2"
+                "flatted": "^3.2.9",
+                "keyv": "^4.5.4"
             },
             "engines": {
-                "node": "^10.12.0 || >=12.0.0"
+                "node": ">=16"
             }
         },
         "node_modules/flatted": {
-            "version": "3.2.7",
-            "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
-            "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
-            "dev": true
+            "version": "3.3.3",
+            "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
+            "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+            "dev": true,
+            "license": "ISC"
         },
         "node_modules/follow-redirects": {
-            "version": "1.15.6",
-            "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
-            "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
+            "version": "1.15.9",
+            "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
+            "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
             "dev": true,
             "funding": [
                 {
@@ -3003,6 +3308,7 @@
                     "url": "https://github.com/sponsors/RubenVerborgh"
                 }
             ],
+            "license": "MIT",
             "engines": {
                 "node": ">=4.0"
             },
@@ -3030,14 +3336,15 @@
             }
         },
         "node_modules/form-data": {
-            "version": "4.0.1",
-            "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz",
-            "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
+            "version": "4.0.2",
+            "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
+            "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
             "dev": true,
             "license": "MIT",
             "dependencies": {
                 "asynckit": "^0.4.0",
                 "combined-stream": "^1.0.8",
+                "es-set-tostringtag": "^2.1.0",
                 "mime-types": "^2.1.12"
             },
             "engines": {
@@ -3049,14 +3356,9 @@
             "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
             "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
             "dev": true,
+            "license": "MIT",
             "optional": true
         },
-        "node_modules/fs.realpath": {
-            "version": "1.0.0",
-            "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-            "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
-            "dev": true
-        },
         "node_modules/function-bind": {
             "version": "1.1.2",
             "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
@@ -3071,22 +3373,28 @@
             "version": "2.0.5",
             "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
             "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+            "license": "ISC",
             "engines": {
                 "node": "6.* || 8.* || >= 10.*"
             }
         },
         "node_modules/get-intrinsic": {
-            "version": "1.2.4",
-            "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
-            "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
+            "version": "1.3.0",
+            "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+            "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
             "dev": true,
             "license": "MIT",
             "dependencies": {
+                "call-bind-apply-helpers": "^1.0.2",
+                "es-define-property": "^1.0.1",
                 "es-errors": "^1.3.0",
+                "es-object-atoms": "^1.1.1",
                 "function-bind": "^1.1.2",
-                "has-proto": "^1.0.1",
-                "has-symbols": "^1.0.3",
-                "hasown": "^2.0.0"
+                "get-proto": "^1.0.1",
+                "gopd": "^1.2.0",
+                "has-symbols": "^1.1.0",
+                "hasown": "^2.0.2",
+                "math-intrinsics": "^1.1.0"
             },
             "engines": {
                 "node": ">= 0.4"
@@ -3095,28 +3403,47 @@
                 "url": "https://github.com/sponsors/ljharb"
             }
         },
+        "node_modules/get-proto": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+            "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "dunder-proto": "^1.0.1",
+                "es-object-atoms": "^1.0.0"
+            },
+            "engines": {
+                "node": ">= 0.4"
+            }
+        },
         "node_modules/github-from-package": {
             "version": "0.0.0",
             "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
             "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
             "dev": true,
+            "license": "MIT",
             "optional": true
         },
         "node_modules/glob": {
-            "version": "7.2.3",
-            "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
-            "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+            "version": "11.0.1",
+            "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.1.tgz",
+            "integrity": "sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==",
             "dev": true,
+            "license": "ISC",
             "dependencies": {
-                "fs.realpath": "^1.0.0",
-                "inflight": "^1.0.4",
-                "inherits": "2",
-                "minimatch": "^3.1.1",
-                "once": "^1.3.0",
-                "path-is-absolute": "^1.0.0"
+                "foreground-child": "^3.1.0",
+                "jackspeak": "^4.0.1",
+                "minimatch": "^10.0.0",
+                "minipass": "^7.1.2",
+                "package-json-from-dist": "^1.0.0",
+                "path-scurry": "^2.0.0"
+            },
+            "bin": {
+                "glob": "dist/esm/bin.mjs"
             },
             "engines": {
-                "node": "*"
+                "node": "20 || >=22"
             },
             "funding": {
                 "url": "https://github.com/sponsors/isaacs"
@@ -3127,6 +3454,7 @@
             "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
             "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
             "dev": true,
+            "license": "ISC",
             "dependencies": {
                 "is-glob": "^4.0.3"
             },
@@ -3134,92 +3462,69 @@
                 "node": ">=10.13.0"
             }
         },
-        "node_modules/globals": {
-            "version": "13.20.0",
-            "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz",
-            "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==",
+        "node_modules/glob/node_modules/minimatch": {
+            "version": "10.0.1",
+            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
+            "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
             "dev": true,
+            "license": "ISC",
             "dependencies": {
-                "type-fest": "^0.20.2"
+                "brace-expansion": "^2.0.1"
             },
             "engines": {
-                "node": ">=8"
+                "node": "20 || >=22"
             },
             "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
+                "url": "https://github.com/sponsors/isaacs"
             }
         },
-        "node_modules/globby": {
-            "version": "11.1.0",
-            "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
-            "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+        "node_modules/globals": {
+            "version": "14.0.0",
+            "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+            "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
             "dev": true,
-            "dependencies": {
-                "array-union": "^2.1.0",
-                "dir-glob": "^3.0.1",
-                "fast-glob": "^3.2.9",
-                "ignore": "^5.2.0",
-                "merge2": "^1.4.1",
-                "slash": "^3.0.0"
-            },
+            "license": "MIT",
             "engines": {
-                "node": ">=10"
+                "node": ">=18"
             },
             "funding": {
                 "url": "https://github.com/sponsors/sindresorhus"
             }
         },
         "node_modules/gopd": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
-            "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+            "version": "1.2.0",
+            "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+            "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
             "dev": true,
             "license": "MIT",
-            "dependencies": {
-                "get-intrinsic": "^1.1.3"
+            "engines": {
+                "node": ">= 0.4"
             },
             "funding": {
                 "url": "https://github.com/sponsors/ljharb"
             }
         },
-        "node_modules/grapheme-splitter": {
-            "version": "1.0.4",
-            "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
-            "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
-            "dev": true
-        },
         "node_modules/graphemer": {
             "version": "1.4.0",
             "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
             "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
-            "dev": true
-        },
-        "node_modules/has-flag": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-            "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
             "dev": true,
-            "engines": {
-                "node": ">=8"
-            }
+            "license": "MIT"
         },
-        "node_modules/has-property-descriptors": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
-            "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+        "node_modules/has-flag": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+            "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
             "dev": true,
             "license": "MIT",
-            "dependencies": {
-                "es-define-property": "^1.0.0"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/ljharb"
+            "engines": {
+                "node": ">=4"
             }
         },
-        "node_modules/has-proto": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
-            "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
+        "node_modules/has-symbols": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+            "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
             "dev": true,
             "license": "MIT",
             "engines": {
@@ -3229,12 +3534,15 @@
                 "url": "https://github.com/sponsors/ljharb"
             }
         },
-        "node_modules/has-symbols": {
-            "version": "1.0.3",
-            "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
-            "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+        "node_modules/has-tostringtag": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+            "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
             "dev": true,
             "license": "MIT",
+            "dependencies": {
+                "has-symbols": "^1.0.3"
+            },
             "engines": {
                 "node": ">= 0.4"
             },
@@ -3260,6 +3568,7 @@
             "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
             "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
             "dev": true,
+            "license": "ISC",
             "dependencies": {
                 "lru-cache": "^6.0.0"
             },
@@ -3268,9 +3577,9 @@
             }
         },
         "node_modules/htmlparser2": {
-            "version": "8.0.1",
-            "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz",
-            "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==",
+            "version": "9.1.0",
+            "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz",
+            "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==",
             "dev": true,
             "funding": [
                 "https://github.com/fb55/htmlparser2?sponsor=1",
@@ -3279,44 +3588,47 @@
                     "url": "https://github.com/sponsors/fb55"
                 }
             ],
+            "license": "MIT",
             "dependencies": {
                 "domelementtype": "^2.3.0",
-                "domhandler": "^5.0.2",
-                "domutils": "^3.0.1",
-                "entities": "^4.3.0"
+                "domhandler": "^5.0.3",
+                "domutils": "^3.1.0",
+                "entities": "^4.5.0"
             }
         },
         "node_modules/http-proxy-agent": {
-            "version": "4.0.1",
-            "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
-            "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
+            "version": "7.0.2",
+            "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
+            "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "@tootallnate/once": "1",
-                "agent-base": "6",
-                "debug": "4"
+                "agent-base": "^7.1.0",
+                "debug": "^4.3.4"
             },
             "engines": {
-                "node": ">= 6"
+                "node": ">= 14"
             }
         },
         "node_modules/https-proxy-agent": {
-            "version": "5.0.1",
-            "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
-            "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+            "version": "7.0.6",
+            "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
+            "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "agent-base": "6",
+                "agent-base": "^7.1.2",
                 "debug": "4"
             },
             "engines": {
-                "node": ">= 6"
+                "node": ">= 14"
             }
         },
         "node_modules/iconv-lite": {
             "version": "0.6.3",
             "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
             "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+            "license": "MIT",
             "dependencies": {
                 "safer-buffer": ">= 2.1.2 < 3.0.0"
             },
@@ -3343,13 +3655,14 @@
                     "url": "https://feross.org/support"
                 }
             ],
-            "optional": true
+            "license": "BSD-3-Clause"
         },
         "node_modules/ignore": {
-            "version": "5.2.4",
-            "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
-            "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
+            "version": "5.3.2",
+            "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+            "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": ">= 4"
             }
@@ -3358,13 +3671,15 @@
             "version": "3.0.6",
             "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
             "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
-            "dev": true
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/import-fresh": {
-            "version": "3.3.0",
-            "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
-            "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+            "version": "3.3.1",
+            "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+            "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "parent-module": "^1.0.0",
                 "resolve-from": "^4.0.0"
@@ -3381,37 +3696,31 @@
             "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
             "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": ">=0.8.19"
             }
         },
-        "node_modules/inflight": {
-            "version": "1.0.6",
-            "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
-            "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
-            "dev": true,
-            "dependencies": {
-                "once": "^1.3.0",
-                "wrappy": "1"
-            }
-        },
         "node_modules/inherits": {
             "version": "2.0.4",
             "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
             "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
-            "dev": true
+            "dev": true,
+            "license": "ISC"
         },
         "node_modules/ini": {
             "version": "1.3.8",
             "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
             "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
             "dev": true,
+            "license": "ISC",
             "optional": true
         },
         "node_modules/internmap": {
             "version": "2.0.3",
             "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
             "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
+            "license": "ISC",
             "engines": {
                 "node": ">=12"
             }
@@ -3421,6 +3730,7 @@
             "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz",
             "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "ci-info": "^2.0.0"
             },
@@ -3429,16 +3739,16 @@
             }
         },
         "node_modules/is-docker": {
-            "version": "2.2.1",
-            "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
-            "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
+            "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
             "dev": true,
             "license": "MIT",
             "bin": {
                 "is-docker": "cli.js"
             },
             "engines": {
-                "node": ">=8"
+                "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
             },
             "funding": {
                 "url": "https://github.com/sponsors/sindresorhus"
@@ -3449,6 +3759,7 @@
             "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
             "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": ">=0.10.0"
             }
@@ -3457,6 +3768,7 @@
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
             "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+            "license": "MIT",
             "engines": {
                 "node": ">=8"
             }
@@ -3466,6 +3778,7 @@
             "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
             "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "is-extglob": "^2.1.1"
             },
@@ -3473,53 +3786,95 @@
                 "node": ">=0.10.0"
             }
         },
+        "node_modules/is-inside-container": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
+            "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "is-docker": "^3.0.0"
+            },
+            "bin": {
+                "is-inside-container": "cli.js"
+            },
+            "engines": {
+                "node": ">=14.16"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/is-interactive": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-2.0.0.tgz",
+            "integrity": "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
         "node_modules/is-number": {
             "version": "7.0.0",
             "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
             "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": ">=0.12.0"
             }
         },
-        "node_modules/is-path-inside": {
-            "version": "3.0.3",
-            "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
-            "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+        "node_modules/is-unicode-supported": {
+            "version": "1.3.0",
+            "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz",
+            "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==",
             "dev": true,
+            "license": "MIT",
             "engines": {
-                "node": ">=8"
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
             }
         },
         "node_modules/is-wsl": {
-            "version": "2.2.0",
-            "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
-            "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz",
+            "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==",
             "dev": true,
             "license": "MIT",
             "dependencies": {
-                "is-docker": "^2.0.0"
+                "is-inside-container": "^1.0.0"
             },
             "engines": {
-                "node": ">=8"
+                "node": ">=16"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
             }
         },
         "node_modules/isarray": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
             "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
-            "dev": true
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/isexe": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
             "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
-            "dev": true
+            "dev": true,
+            "license": "ISC"
         },
         "node_modules/jackspeak": {
-            "version": "4.0.2",
-            "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz",
-            "integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==",
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.0.tgz",
+            "integrity": "sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw==",
             "dev": true,
             "license": "BlueOak-1.0.0",
             "dependencies": {
@@ -3532,11 +3887,21 @@
                 "url": "https://github.com/sponsors/isaacs"
             }
         },
+        "node_modules/jiti": {
+            "version": "2.4.2",
+            "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz",
+            "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==",
+            "license": "MIT",
+            "bin": {
+                "jiti": "lib/jiti-cli.mjs"
+            }
+        },
         "node_modules/js-yaml": {
             "version": "4.1.0",
             "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
             "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "argparse": "^2.0.1"
             },
@@ -3544,23 +3909,33 @@
                 "js-yaml": "bin/js-yaml.js"
             }
         },
+        "node_modules/json-buffer": {
+            "version": "3.0.1",
+            "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+            "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+            "dev": true,
+            "license": "MIT"
+        },
         "node_modules/json-schema-traverse": {
             "version": "0.4.1",
             "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
             "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
-            "dev": true
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/json-stable-stringify-without-jsonify": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
             "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
-            "dev": true
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/jsonc-parser": {
-            "version": "3.2.0",
-            "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz",
-            "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==",
-            "dev": true
+            "version": "3.3.1",
+            "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz",
+            "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==",
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/jsonwebtoken": {
             "version": "9.0.2",
@@ -3613,6 +3988,7 @@
             "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
             "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
             "dev": true,
+            "license": "(MIT OR GPL-3.0-or-later)",
             "dependencies": {
                 "lie": "~3.3.0",
                 "pako": "~1.0.2",
@@ -3649,17 +4025,29 @@
             "integrity": "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ==",
             "dev": true,
             "hasInstallScript": true,
+            "license": "MIT",
             "optional": true,
             "dependencies": {
                 "node-addon-api": "^4.3.0",
                 "prebuild-install": "^7.0.1"
             }
         },
+        "node_modules/keyv": {
+            "version": "4.5.4",
+            "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+            "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "json-buffer": "3.0.1"
+            }
+        },
         "node_modules/leven": {
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
             "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": ">=6"
             }
@@ -3669,6 +4057,7 @@
             "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
             "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "prelude-ls": "^1.2.1",
                 "type-check": "~0.4.0"
@@ -3682,6 +4071,7 @@
             "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
             "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "immediate": "~3.0.5"
             }
@@ -3701,6 +4091,7 @@
             "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
             "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "p-locate": "^5.0.0"
             },
@@ -3757,7 +4148,8 @@
             "version": "4.6.2",
             "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
             "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
-            "dev": true
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/lodash.once": {
             "version": "4.1.1",
@@ -3766,10 +4158,42 @@
             "dev": true,
             "license": "MIT"
         },
+        "node_modules/log-symbols": {
+            "version": "5.1.0",
+            "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-5.1.0.tgz",
+            "integrity": "sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "chalk": "^5.0.0",
+                "is-unicode-supported": "^1.1.0"
+            },
+            "engines": {
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/log-symbols/node_modules/chalk": {
+            "version": "5.4.1",
+            "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz",
+            "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": "^12.17.0 || ^14.13 || >=16.0.0"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/chalk?sponsor=1"
+            }
+        },
         "node_modules/lru-cache": {
             "version": "6.0.0",
             "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
             "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+            "dev": true,
+            "license": "ISC",
             "dependencies": {
                 "yallist": "^4.0.0"
             },
@@ -3795,6 +4219,16 @@
                 "markdown-it": "bin/markdown-it.mjs"
             }
         },
+        "node_modules/math-intrinsics": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+            "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">= 0.4"
+            }
+        },
         "node_modules/mdurl": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
@@ -3807,6 +4241,7 @@
             "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
             "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": ">= 8"
             }
@@ -3825,11 +4260,25 @@
                 "node": ">=8.6"
             }
         },
+        "node_modules/micromatch/node_modules/picomatch": {
+            "version": "2.3.1",
+            "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+            "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=8.6"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/jonschlinkert"
+            }
+        },
         "node_modules/mime": {
             "version": "1.6.0",
             "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
             "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
             "dev": true,
+            "license": "MIT",
             "bin": {
                 "mime": "cli.js"
             },
@@ -3860,11 +4309,22 @@
                 "node": ">= 0.6"
             }
         },
+        "node_modules/mimic-fn": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+            "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=6"
+            }
+        },
         "node_modules/mimic-response": {
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
             "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
             "dev": true,
+            "license": "MIT",
             "optional": true,
             "engines": {
                 "node": ">=10"
@@ -3874,22 +4334,27 @@
             }
         },
         "node_modules/minimatch": {
-            "version": "3.1.2",
-            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
-            "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+            "version": "9.0.5",
+            "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+            "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
             "dev": true,
+            "license": "ISC",
             "dependencies": {
-                "brace-expansion": "^1.1.7"
+                "brace-expansion": "^2.0.1"
             },
             "engines": {
-                "node": "*"
+                "node": ">=16 || 14 >=14.17"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/isaacs"
             }
         },
         "node_modules/minimist": {
-            "version": "1.2.7",
-            "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz",
-            "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==",
+            "version": "1.2.8",
+            "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+            "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
             "dev": true,
+            "license": "MIT",
             "optional": true,
             "funding": {
                 "url": "https://github.com/sponsors/ljharb"
@@ -3910,44 +4375,44 @@
             "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
             "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
             "dev": true,
+            "license": "MIT",
             "optional": true
         },
         "node_modules/ms": {
-            "version": "2.1.2",
-            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-            "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-            "dev": true
+            "version": "2.1.3",
+            "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+            "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/mute-stream": {
             "version": "0.0.8",
             "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
             "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
-            "dev": true
+            "dev": true,
+            "license": "ISC"
         },
         "node_modules/napi-build-utils": {
-            "version": "1.0.2",
-            "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
-            "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==",
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz",
+            "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==",
             "dev": true,
+            "license": "MIT",
             "optional": true
         },
         "node_modules/natural-compare": {
             "version": "1.4.0",
             "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
             "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
-            "dev": true
-        },
-        "node_modules/natural-compare-lite": {
-            "version": "1.4.0",
-            "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
-            "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
-            "dev": true
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/node-abi": {
-            "version": "3.31.0",
-            "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.31.0.tgz",
-            "integrity": "sha512-eSKV6s+APenqVh8ubJyiu/YhZgxQpGP66ntzUb3lY1xB9ukSRaGnx0AIxI+IM+1+IVYC1oWobgG5L3Lt9ARykQ==",
+            "version": "3.74.0",
+            "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.74.0.tgz",
+            "integrity": "sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w==",
             "dev": true,
+            "license": "MIT",
             "optional": true,
             "dependencies": {
                 "semver": "^7.3.5"
@@ -3961,6 +4426,7 @@
             "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz",
             "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==",
             "dev": true,
+            "license": "MIT",
             "optional": true
         },
         "node_modules/nth-check": {
@@ -3968,6 +4434,7 @@
             "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
             "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
             "dev": true,
+            "license": "BSD-2-Clause",
             "dependencies": {
                 "boolbase": "^1.0.0"
             },
@@ -3976,9 +4443,9 @@
             }
         },
         "node_modules/object-inspect": {
-            "version": "1.13.2",
-            "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz",
-            "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==",
+            "version": "1.13.4",
+            "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
+            "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
             "dev": true,
             "license": "MIT",
             "engines": {
@@ -3993,251 +4460,180 @@
             "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
             "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
             "dev": true,
+            "license": "ISC",
+            "optional": true,
             "dependencies": {
                 "wrappy": "1"
             }
         },
+        "node_modules/onetime": {
+            "version": "5.1.2",
+            "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+            "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "mimic-fn": "^2.1.0"
+            },
+            "engines": {
+                "node": ">=6"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
         "node_modules/open": {
-            "version": "8.4.2",
-            "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz",
-            "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==",
+            "version": "10.1.0",
+            "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz",
+            "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==",
             "dev": true,
             "license": "MIT",
             "dependencies": {
-                "define-lazy-prop": "^2.0.0",
-                "is-docker": "^2.1.1",
-                "is-wsl": "^2.2.0"
+                "default-browser": "^5.2.1",
+                "define-lazy-prop": "^3.0.0",
+                "is-inside-container": "^1.0.0",
+                "is-wsl": "^3.1.0"
             },
             "engines": {
-                "node": ">=12"
+                "node": ">=18"
             },
             "funding": {
                 "url": "https://github.com/sponsors/sindresorhus"
             }
         },
         "node_modules/optionator": {
-            "version": "0.9.3",
-            "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
-            "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
+            "version": "0.9.4",
+            "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+            "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "@aashutoshrathi/word-wrap": "^1.2.3",
                 "deep-is": "^0.1.3",
                 "fast-levenshtein": "^2.0.6",
                 "levn": "^0.4.1",
                 "prelude-ls": "^1.2.1",
-                "type-check": "^0.4.0"
+                "type-check": "^0.4.0",
+                "word-wrap": "^1.2.5"
             },
             "engines": {
                 "node": ">= 0.8.0"
             }
         },
-        "node_modules/ovsx": {
-            "version": "0.8.2",
-            "resolved": "https://registry.npmjs.org/ovsx/-/ovsx-0.8.2.tgz",
-            "integrity": "sha512-btDXZorXlmwN9+9Un3khrVygCXmhwbrtg8gifNXw92rZPXcRBAiLG/L09Kb6srhGEratsFt42AktfD8t9XhzoA==",
+        "node_modules/ora": {
+            "version": "7.0.1",
+            "resolved": "https://registry.npmjs.org/ora/-/ora-7.0.1.tgz",
+            "integrity": "sha512-0TUxTiFJWv+JnjWm4o9yvuskpEJLXTcng8MJuKd+SzAzp2o+OP3HWqNhB4OdJRt1Vsd9/mR0oyaEYlOnL7XIRw==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "@vscode/vsce": "^2.19.0",
-                "commander": "^6.1.0",
-                "follow-redirects": "^1.14.6",
-                "is-ci": "^2.0.0",
-                "leven": "^3.1.0",
-                "semver": "^7.5.2",
-                "tmp": "^0.2.1"
-            },
-            "bin": {
-                "ovsx": "lib/ovsx"
+                "chalk": "^5.3.0",
+                "cli-cursor": "^4.0.0",
+                "cli-spinners": "^2.9.0",
+                "is-interactive": "^2.0.0",
+                "is-unicode-supported": "^1.3.0",
+                "log-symbols": "^5.1.0",
+                "stdin-discarder": "^0.1.0",
+                "string-width": "^6.1.0",
+                "strip-ansi": "^7.1.0"
             },
             "engines": {
-                "node": ">= 14"
+                "node": ">=16"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
             }
         },
-        "node_modules/ovsx/node_modules/@vscode/vsce": {
-            "version": "2.32.0",
-            "resolved": "https://registry.npmjs.org/@vscode/vsce/-/vsce-2.32.0.tgz",
-            "integrity": "sha512-3EFJfsgrSftIqt3EtdRcAygy/OJ3hstyI1cDmIgkU9CFZW5C+3djr6mfosndCUqcVYuyjmxOK1xmFp/Bq7+NIg==",
+        "node_modules/ora/node_modules/chalk": {
+            "version": "5.4.1",
+            "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz",
+            "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==",
             "dev": true,
             "license": "MIT",
-            "dependencies": {
-                "@azure/identity": "^4.1.0",
-                "@vscode/vsce-sign": "^2.0.0",
-                "azure-devops-node-api": "^12.5.0",
-                "chalk": "^2.4.2",
-                "cheerio": "^1.0.0-rc.9",
-                "cockatiel": "^3.1.2",
-                "commander": "^6.2.1",
-                "form-data": "^4.0.0",
-                "glob": "^7.0.6",
-                "hosted-git-info": "^4.0.2",
-                "jsonc-parser": "^3.2.0",
-                "leven": "^3.1.0",
-                "markdown-it": "^12.3.2",
-                "mime": "^1.3.4",
-                "minimatch": "^3.0.3",
-                "parse-semver": "^1.1.1",
-                "read": "^1.0.7",
-                "semver": "^7.5.2",
-                "tmp": "^0.2.1",
-                "typed-rest-client": "^1.8.4",
-                "url-join": "^4.0.1",
-                "xml2js": "^0.5.0",
-                "yauzl": "^2.3.1",
-                "yazl": "^2.2.2"
-            },
-            "bin": {
-                "vsce": "vsce"
-            },
             "engines": {
-                "node": ">= 16"
+                "node": "^12.17.0 || ^14.13 || >=16.0.0"
             },
-            "optionalDependencies": {
-                "keytar": "^7.7.0"
+            "funding": {
+                "url": "https://github.com/chalk/chalk?sponsor=1"
             }
         },
-        "node_modules/ovsx/node_modules/ansi-styles": {
-            "version": "3.2.1",
-            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-            "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+        "node_modules/ora/node_modules/emoji-regex": {
+            "version": "10.4.0",
+            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz",
+            "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==",
             "dev": true,
-            "license": "MIT",
-            "dependencies": {
-                "color-convert": "^1.9.0"
-            },
-            "engines": {
-                "node": ">=4"
-            }
+            "license": "MIT"
         },
-        "node_modules/ovsx/node_modules/chalk": {
-            "version": "2.4.2",
-            "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-            "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+        "node_modules/ora/node_modules/string-width": {
+            "version": "6.1.0",
+            "resolved": "https://registry.npmjs.org/string-width/-/string-width-6.1.0.tgz",
+            "integrity": "sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ==",
             "dev": true,
             "license": "MIT",
             "dependencies": {
-                "ansi-styles": "^3.2.1",
-                "escape-string-regexp": "^1.0.5",
-                "supports-color": "^5.3.0"
+                "eastasianwidth": "^0.2.0",
+                "emoji-regex": "^10.2.1",
+                "strip-ansi": "^7.0.1"
             },
             "engines": {
-                "node": ">=4"
+                "node": ">=16"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
             }
         },
-        "node_modules/ovsx/node_modules/color-convert": {
-            "version": "1.9.3",
-            "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
-            "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+        "node_modules/ovsx": {
+            "version": "0.10.1",
+            "resolved": "https://registry.npmjs.org/ovsx/-/ovsx-0.10.1.tgz",
+            "integrity": "sha512-8i7+MJMMeq73m1zPEIClSFe17SNuuzU5br7G77ZIfOC24elB4pGQs0N1qRd+gnnbyhL5Qu96G21nFOVOBa2OBg==",
             "dev": true,
-            "license": "MIT",
+            "license": "EPL-2.0",
             "dependencies": {
-                "color-name": "1.1.3"
+                "@vscode/vsce": "^3.2.1",
+                "commander": "^6.2.1",
+                "follow-redirects": "^1.14.6",
+                "is-ci": "^2.0.0",
+                "leven": "^3.1.0",
+                "semver": "^7.6.0",
+                "tmp": "^0.2.3",
+                "yauzl": "^3.1.3"
+            },
+            "bin": {
+                "ovsx": "lib/ovsx"
+            },
+            "engines": {
+                "node": ">= 20"
             }
         },
-        "node_modules/ovsx/node_modules/color-name": {
-            "version": "1.1.3",
-            "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-            "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
-            "dev": true,
-            "license": "MIT"
-        },
         "node_modules/ovsx/node_modules/commander": {
             "version": "6.2.1",
             "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
             "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
             "dev": true,
-            "engines": {
-                "node": ">= 6"
-            }
-        },
-        "node_modules/ovsx/node_modules/entities": {
-            "version": "2.1.0",
-            "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
-            "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==",
-            "dev": true,
-            "license": "BSD-2-Clause",
-            "funding": {
-                "url": "https://github.com/fb55/entities?sponsor=1"
-            }
-        },
-        "node_modules/ovsx/node_modules/escape-string-regexp": {
-            "version": "1.0.5",
-            "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-            "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
-            "dev": true,
-            "license": "MIT",
-            "engines": {
-                "node": ">=0.8.0"
-            }
-        },
-        "node_modules/ovsx/node_modules/has-flag": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-            "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
-            "dev": true,
             "license": "MIT",
             "engines": {
-                "node": ">=4"
-            }
-        },
-        "node_modules/ovsx/node_modules/linkify-it": {
-            "version": "3.0.3",
-            "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz",
-            "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==",
-            "dev": true,
-            "license": "MIT",
-            "dependencies": {
-                "uc.micro": "^1.0.1"
-            }
-        },
-        "node_modules/ovsx/node_modules/markdown-it": {
-            "version": "12.3.2",
-            "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz",
-            "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==",
-            "dev": true,
-            "license": "MIT",
-            "dependencies": {
-                "argparse": "^2.0.1",
-                "entities": "~2.1.0",
-                "linkify-it": "^3.0.1",
-                "mdurl": "^1.0.1",
-                "uc.micro": "^1.0.5"
-            },
-            "bin": {
-                "markdown-it": "bin/markdown-it.js"
+                "node": ">= 6"
             }
         },
-        "node_modules/ovsx/node_modules/mdurl": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
-            "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==",
-            "dev": true,
-            "license": "MIT"
-        },
-        "node_modules/ovsx/node_modules/supports-color": {
-            "version": "5.5.0",
-            "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-            "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+        "node_modules/ovsx/node_modules/yauzl": {
+            "version": "3.2.0",
+            "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-3.2.0.tgz",
+            "integrity": "sha512-Ow9nuGZE+qp1u4JIPvg+uCiUr7xGQWdff7JQSk5VGYTAZMDe2q8lxJ10ygv10qmSj031Ty/6FNJpLO4o1Sgc+w==",
             "dev": true,
             "license": "MIT",
             "dependencies": {
-                "has-flag": "^3.0.0"
+                "buffer-crc32": "~0.2.3",
+                "pend": "~1.2.0"
             },
             "engines": {
-                "node": ">=4"
+                "node": ">=12"
             }
         },
-        "node_modules/ovsx/node_modules/uc.micro": {
-            "version": "1.0.6",
-            "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
-            "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
-            "dev": true,
-            "license": "MIT"
-        },
         "node_modules/p-limit": {
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
             "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "yocto-queue": "^0.1.0"
             },
@@ -4253,6 +4649,7 @@
             "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
             "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "p-limit": "^3.0.2"
             },
@@ -4274,13 +4671,15 @@
             "version": "1.0.11",
             "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
             "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
-            "dev": true
+            "dev": true,
+            "license": "(MIT AND Zlib)"
         },
         "node_modules/parent-module": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
             "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "callsites": "^3.0.0"
             },
@@ -4293,6 +4692,7 @@
             "resolved": "https://registry.npmjs.org/parse-semver/-/parse-semver-1.1.1.tgz",
             "integrity": "sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "semver": "^5.1.0"
             }
@@ -4302,29 +4702,45 @@
             "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
             "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
             "dev": true,
+            "license": "ISC",
             "bin": {
                 "semver": "bin/semver"
             }
         },
         "node_modules/parse5": {
-            "version": "7.1.2",
-            "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz",
-            "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==",
+            "version": "7.2.1",
+            "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz",
+            "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "entities": "^4.4.0"
+                "entities": "^4.5.0"
             },
             "funding": {
                 "url": "https://github.com/inikulin/parse5?sponsor=1"
             }
         },
         "node_modules/parse5-htmlparser2-tree-adapter": {
-            "version": "7.0.0",
-            "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz",
-            "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==",
+            "version": "7.1.0",
+            "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz",
+            "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==",
             "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "domhandler": "^5.0.3",
+                "parse5": "^7.0.0"
+            },
+            "funding": {
+                "url": "https://github.com/inikulin/parse5?sponsor=1"
+            }
+        },
+        "node_modules/parse5-parser-stream": {
+            "version": "7.1.2",
+            "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz",
+            "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==",
+            "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "domhandler": "^5.0.2",
                 "parse5": "^7.0.0"
             },
             "funding": {
@@ -4336,24 +4752,17 @@
             "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
             "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": ">=8"
             }
         },
-        "node_modules/path-is-absolute": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-            "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
-            "dev": true,
-            "engines": {
-                "node": ">=0.10.0"
-            }
-        },
         "node_modules/path-key": {
             "version": "3.1.1",
             "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
             "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": ">=8"
             }
@@ -4376,47 +4785,41 @@
             }
         },
         "node_modules/path-scurry/node_modules/lru-cache": {
-            "version": "11.0.1",
-            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.1.tgz",
-            "integrity": "sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ==",
+            "version": "11.0.2",
+            "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz",
+            "integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==",
             "dev": true,
             "license": "ISC",
             "engines": {
                 "node": "20 || >=22"
             }
         },
-        "node_modules/path-type": {
-            "version": "4.0.0",
-            "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
-            "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
-            "dev": true,
-            "engines": {
-                "node": ">=8"
-            }
-        },
         "node_modules/pend": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
             "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
-            "dev": true
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/picomatch": {
-            "version": "2.3.1",
-            "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
-            "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+            "version": "4.0.2",
+            "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
+            "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
             "dev": true,
+            "license": "MIT",
             "engines": {
-                "node": ">=8.6"
+                "node": ">=12"
             },
             "funding": {
                 "url": "https://github.com/sponsors/jonschlinkert"
             }
         },
         "node_modules/prebuild-install": {
-            "version": "7.1.1",
-            "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz",
-            "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==",
+            "version": "7.1.3",
+            "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
+            "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==",
             "dev": true,
+            "license": "MIT",
             "optional": true,
             "dependencies": {
                 "detect-libc": "^2.0.0",
@@ -4424,7 +4827,7 @@
                 "github-from-package": "0.0.0",
                 "minimist": "^1.2.3",
                 "mkdirp-classic": "^0.5.3",
-                "napi-build-utils": "^1.0.1",
+                "napi-build-utils": "^2.0.0",
                 "node-abi": "^3.3.0",
                 "pump": "^3.0.0",
                 "rc": "^1.2.7",
@@ -4444,15 +4847,17 @@
             "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
             "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": ">= 0.8.0"
             }
         },
         "node_modules/prettier": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.0.tgz",
-            "integrity": "sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==",
+            "version": "3.5.2",
+            "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.2.tgz",
+            "integrity": "sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg==",
             "dev": true,
+            "license": "MIT",
             "bin": {
                 "prettier": "bin/prettier.cjs"
             },
@@ -4467,13 +4872,15 @@
             "version": "2.0.1",
             "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
             "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
-            "dev": true
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/pump": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
-            "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+            "version": "3.0.2",
+            "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz",
+            "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==",
             "dev": true,
+            "license": "MIT",
             "optional": true,
             "dependencies": {
                 "end-of-stream": "^1.1.0",
@@ -4481,10 +4888,11 @@
             }
         },
         "node_modules/punycode": {
-            "version": "2.3.0",
-            "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
-            "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
+            "version": "2.3.1",
+            "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+            "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": ">=6"
             }
@@ -4500,13 +4908,13 @@
             }
         },
         "node_modules/qs": {
-            "version": "6.13.0",
-            "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz",
-            "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
+            "version": "6.14.0",
+            "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
+            "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
             "dev": true,
             "license": "BSD-3-Clause",
             "dependencies": {
-                "side-channel": "^1.0.6"
+                "side-channel": "^1.1.0"
             },
             "engines": {
                 "node": ">=0.6"
@@ -4533,13 +4941,15 @@
                     "type": "consulting",
                     "url": "https://feross.org/support"
                 }
-            ]
+            ],
+            "license": "MIT"
         },
         "node_modules/rc": {
             "version": "1.2.8",
             "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
             "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
             "dev": true,
+            "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
             "optional": true,
             "dependencies": {
                 "deep-extend": "^0.6.0",
@@ -4556,6 +4966,7 @@
             "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
             "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
             "dev": true,
+            "license": "MIT",
             "optional": true,
             "engines": {
                 "node": ">=0.10.0"
@@ -4566,6 +4977,7 @@
             "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
             "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==",
             "dev": true,
+            "license": "ISC",
             "dependencies": {
                 "mute-stream": "~0.0.4"
             },
@@ -4578,6 +4990,7 @@
             "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
             "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "core-util-is": "~1.0.0",
                 "inherits": "~2.0.3",
@@ -4588,10 +5001,18 @@
                 "util-deprecate": "~1.0.1"
             }
         },
+        "node_modules/readable-stream/node_modules/safe-buffer": {
+            "version": "5.1.2",
+            "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+            "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+            "dev": true,
+            "license": "MIT"
+        },
         "node_modules/require-directory": {
             "version": "2.1.1",
             "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
             "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+            "license": "MIT",
             "engines": {
                 "node": ">=0.10.0"
             }
@@ -4601,40 +5022,65 @@
             "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
             "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": ">=4"
             }
         },
+        "node_modules/restore-cursor": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz",
+            "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "onetime": "^5.1.0",
+                "signal-exit": "^3.0.2"
+            },
+            "engines": {
+                "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/restore-cursor/node_modules/signal-exit": {
+            "version": "3.0.7",
+            "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+            "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+            "dev": true,
+            "license": "ISC"
+        },
         "node_modules/reusify": {
             "version": "1.0.4",
             "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
             "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "iojs": ">=1.0.0",
                 "node": ">=0.10.0"
             }
         },
-        "node_modules/rimraf": {
+        "node_modules/robust-predicates": {
             "version": "3.0.2",
-            "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
-            "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+            "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz",
+            "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==",
+            "license": "Unlicense"
+        },
+        "node_modules/run-applescript": {
+            "version": "7.0.0",
+            "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz",
+            "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==",
             "dev": true,
-            "dependencies": {
-                "glob": "^7.1.3"
-            },
-            "bin": {
-                "rimraf": "bin.js"
+            "license": "MIT",
+            "engines": {
+                "node": ">=18"
             },
             "funding": {
-                "url": "https://github.com/sponsors/isaacs"
+                "url": "https://github.com/sponsors/sindresorhus"
             }
         },
-        "node_modules/robust-predicates": {
-            "version": "3.0.1",
-            "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.1.tgz",
-            "integrity": "sha512-ndEIpszUHiG4HtDsQLeIuMvRsDnn8c8rYStabochtUeCvfuvNptb5TUbVD68LRAILPX7p9nqQGh4xJgn3EHS/g=="
-        },
         "node_modules/run-parallel": {
             "version": "1.2.0",
             "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -4654,6 +5100,7 @@
                     "url": "https://feross.org/support"
                 }
             ],
+            "license": "MIT",
             "dependencies": {
                 "queue-microtask": "^1.2.2"
             }
@@ -4661,32 +5108,48 @@
         "node_modules/rw": {
             "version": "1.3.3",
             "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
-            "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ=="
+            "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==",
+            "license": "BSD-3-Clause"
         },
         "node_modules/safe-buffer": {
-            "version": "5.1.2",
-            "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
-            "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
-            "dev": true
+            "version": "5.2.1",
+            "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+            "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+            "dev": true,
+            "funding": [
+                {
+                    "type": "github",
+                    "url": "https://github.com/sponsors/feross"
+                },
+                {
+                    "type": "patreon",
+                    "url": "https://www.patreon.com/feross"
+                },
+                {
+                    "type": "consulting",
+                    "url": "https://feross.org/support"
+                }
+            ],
+            "license": "MIT"
         },
         "node_modules/safer-buffer": {
             "version": "2.1.2",
             "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
-            "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+            "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+            "license": "MIT"
         },
         "node_modules/sax": {
-            "version": "1.2.4",
-            "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
-            "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
-            "dev": true
+            "version": "1.4.1",
+            "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
+            "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
+            "dev": true,
+            "license": "ISC"
         },
         "node_modules/semver": {
-            "version": "7.5.4",
-            "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
-            "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
-            "dependencies": {
-                "lru-cache": "^6.0.0"
-            },
+            "version": "7.7.1",
+            "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
+            "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
+            "license": "ISC",
             "bin": {
                 "semver": "bin/semver.js"
             },
@@ -4694,35 +5157,19 @@
                 "node": ">=10"
             }
         },
-        "node_modules/set-function-length": {
-            "version": "1.2.2",
-            "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
-            "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
-            "dev": true,
-            "license": "MIT",
-            "dependencies": {
-                "define-data-property": "^1.1.4",
-                "es-errors": "^1.3.0",
-                "function-bind": "^1.1.2",
-                "get-intrinsic": "^1.2.4",
-                "gopd": "^1.0.1",
-                "has-property-descriptors": "^1.0.2"
-            },
-            "engines": {
-                "node": ">= 0.4"
-            }
-        },
         "node_modules/setimmediate": {
             "version": "1.0.5",
             "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
             "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
-            "dev": true
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/shebang-command": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
             "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "shebang-regex": "^3.0.0"
             },
@@ -4735,21 +5182,79 @@
             "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
             "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": ">=8"
             }
         },
         "node_modules/side-channel": {
-            "version": "1.0.6",
-            "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
-            "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
+            "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "es-errors": "^1.3.0",
+                "object-inspect": "^1.13.3",
+                "side-channel-list": "^1.0.0",
+                "side-channel-map": "^1.0.1",
+                "side-channel-weakmap": "^1.0.2"
+            },
+            "engines": {
+                "node": ">= 0.4"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/ljharb"
+            }
+        },
+        "node_modules/side-channel-list": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
+            "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
             "dev": true,
             "license": "MIT",
             "dependencies": {
-                "call-bind": "^1.0.7",
                 "es-errors": "^1.3.0",
-                "get-intrinsic": "^1.2.4",
-                "object-inspect": "^1.13.1"
+                "object-inspect": "^1.13.3"
+            },
+            "engines": {
+                "node": ">= 0.4"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/ljharb"
+            }
+        },
+        "node_modules/side-channel-map": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
+            "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "call-bound": "^1.0.2",
+                "es-errors": "^1.3.0",
+                "get-intrinsic": "^1.2.5",
+                "object-inspect": "^1.13.3"
+            },
+            "engines": {
+                "node": ">= 0.4"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/ljharb"
+            }
+        },
+        "node_modules/side-channel-weakmap": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
+            "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "call-bound": "^1.0.2",
+                "es-errors": "^1.3.0",
+                "get-intrinsic": "^1.2.5",
+                "object-inspect": "^1.13.3",
+                "side-channel-map": "^1.0.1"
             },
             "engines": {
                 "node": ">= 0.4"
@@ -4790,6 +5295,7 @@
                     "url": "https://feross.org/support"
                 }
             ],
+            "license": "MIT",
             "optional": true
         },
         "node_modules/simple-get": {
@@ -4811,6 +5317,7 @@
                     "url": "https://feross.org/support"
                 }
             ],
+            "license": "MIT",
             "optional": true,
             "dependencies": {
                 "decompress-response": "^6.0.0",
@@ -4818,13 +5325,20 @@
                 "simple-concat": "^1.0.0"
             }
         },
-        "node_modules/slash": {
-            "version": "3.0.0",
-            "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
-            "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+        "node_modules/stdin-discarder": {
+            "version": "0.1.0",
+            "resolved": "https://registry.npmjs.org/stdin-discarder/-/stdin-discarder-0.1.0.tgz",
+            "integrity": "sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==",
             "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "bl": "^5.0.0"
+            },
             "engines": {
-                "node": ">=8"
+                "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
             }
         },
         "node_modules/stoppable": {
@@ -4843,21 +5357,34 @@
             "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
             "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "safe-buffer": "~5.1.0"
             }
         },
+        "node_modules/string_decoder/node_modules/safe-buffer": {
+            "version": "5.1.2",
+            "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+            "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+            "dev": true,
+            "license": "MIT"
+        },
         "node_modules/string-width": {
-            "version": "4.2.3",
-            "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
-            "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+            "version": "5.1.2",
+            "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+            "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+            "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "emoji-regex": "^8.0.0",
-                "is-fullwidth-code-point": "^3.0.0",
-                "strip-ansi": "^6.0.1"
+                "eastasianwidth": "^0.2.0",
+                "emoji-regex": "^9.2.2",
+                "strip-ansi": "^7.0.1"
             },
             "engines": {
-                "node": ">=8"
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
             }
         },
         "node_modules/string-width-cjs": {
@@ -4876,10 +5403,29 @@
                 "node": ">=8"
             }
         },
-        "node_modules/strip-ansi": {
+        "node_modules/string-width-cjs/node_modules/ansi-regex": {
+            "version": "5.0.1",
+            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/string-width-cjs/node_modules/emoji-regex": {
+            "version": "8.0.0",
+            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+            "dev": true,
+            "license": "MIT"
+        },
+        "node_modules/string-width-cjs/node_modules/strip-ansi": {
             "version": "6.0.1",
             "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
             "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+            "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "ansi-regex": "^5.0.1"
             },
@@ -4887,6 +5433,22 @@
                 "node": ">=8"
             }
         },
+        "node_modules/strip-ansi": {
+            "version": "7.1.0",
+            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+            "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "ansi-regex": "^6.0.1"
+            },
+            "engines": {
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+            }
+        },
         "node_modules/strip-ansi-cjs": {
             "name": "strip-ansi",
             "version": "6.0.1",
@@ -4901,11 +5463,22 @@
                 "node": ">=8"
             }
         },
+        "node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
+            "version": "5.0.1",
+            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=8"
+            }
+        },
         "node_modules/strip-json-comments": {
             "version": "3.1.1",
             "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
             "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": ">=8"
             },
@@ -4914,22 +5487,24 @@
             }
         },
         "node_modules/supports-color": {
-            "version": "7.2.0",
-            "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-            "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+            "version": "5.5.0",
+            "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+            "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "has-flag": "^4.0.0"
+                "has-flag": "^3.0.0"
             },
             "engines": {
-                "node": ">=8"
+                "node": ">=4"
             }
         },
         "node_modules/tar-fs": {
-            "version": "2.1.1",
-            "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
-            "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
+            "version": "2.1.2",
+            "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.2.tgz",
+            "integrity": "sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==",
             "dev": true,
+            "license": "MIT",
             "optional": true,
             "dependencies": {
                 "chownr": "^1.1.1",
@@ -4943,6 +5518,7 @@
             "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
             "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
             "dev": true,
+            "license": "MIT",
             "optional": true,
             "dependencies": {
                 "bl": "^4.0.3",
@@ -4955,11 +5531,51 @@
                 "node": ">=6"
             }
         },
+        "node_modules/tar-stream/node_modules/bl": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+            "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+            "dev": true,
+            "license": "MIT",
+            "optional": true,
+            "dependencies": {
+                "buffer": "^5.5.0",
+                "inherits": "^2.0.4",
+                "readable-stream": "^3.4.0"
+            }
+        },
+        "node_modules/tar-stream/node_modules/buffer": {
+            "version": "5.7.1",
+            "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+            "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+            "dev": true,
+            "funding": [
+                {
+                    "type": "github",
+                    "url": "https://github.com/sponsors/feross"
+                },
+                {
+                    "type": "patreon",
+                    "url": "https://www.patreon.com/feross"
+                },
+                {
+                    "type": "consulting",
+                    "url": "https://feross.org/support"
+                }
+            ],
+            "license": "MIT",
+            "optional": true,
+            "dependencies": {
+                "base64-js": "^1.3.1",
+                "ieee754": "^1.1.13"
+            }
+        },
         "node_modules/tar-stream/node_modules/readable-stream": {
-            "version": "3.6.0",
-            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
-            "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+            "version": "3.6.2",
+            "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+            "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
             "dev": true,
+            "license": "MIT",
             "optional": true,
             "dependencies": {
                 "inherits": "^2.0.3",
@@ -4970,12 +5586,6 @@
                 "node": ">= 6"
             }
         },
-        "node_modules/text-table": {
-            "version": "0.2.0",
-            "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
-            "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
-            "dev": true
-        },
         "node_modules/tmp": {
             "version": "0.2.3",
             "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz",
@@ -4991,6 +5601,7 @@
             "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
             "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "is-number": "^7.0.0"
             },
@@ -4999,21 +5610,22 @@
             }
         },
         "node_modules/ts-api-utils": {
-            "version": "1.0.1",
-            "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz",
-            "integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==",
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz",
+            "integrity": "sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==",
             "dev": true,
+            "license": "MIT",
             "engines": {
-                "node": ">=16.13.0"
+                "node": ">=18.12"
             },
             "peerDependencies": {
-                "typescript": ">=4.2.0"
+                "typescript": ">=4.8.4"
             }
         },
         "node_modules/tslib": {
-            "version": "2.8.0",
-            "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz",
-            "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==",
+            "version": "2.8.1",
+            "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+            "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
             "dev": true,
             "license": "0BSD"
         },
@@ -5032,6 +5644,7 @@
             "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
             "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
             "dev": true,
+            "license": "Apache-2.0",
             "optional": true,
             "dependencies": {
                 "safe-buffer": "^5.0.1"
@@ -5045,6 +5658,7 @@
             "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
             "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "prelude-ls": "^1.2.1"
             },
@@ -5052,18 +5666,6 @@
                 "node": ">= 0.8.0"
             }
         },
-        "node_modules/type-fest": {
-            "version": "0.20.2",
-            "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
-            "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
-            "dev": true,
-            "engines": {
-                "node": ">=10"
-            },
-            "funding": {
-                "url": "https://github.com/sponsors/sindresorhus"
-            }
-        },
         "node_modules/typed-rest-client": {
             "version": "1.8.11",
             "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.11.tgz",
@@ -5077,9 +5679,9 @@
             }
         },
         "node_modules/typescript": {
-            "version": "5.6.3",
-            "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
-            "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
+            "version": "5.7.3",
+            "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
+            "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==",
             "dev": true,
             "license": "Apache-2.0",
             "bin": {
@@ -5090,6 +5692,29 @@
                 "node": ">=14.17"
             }
         },
+        "node_modules/typescript-eslint": {
+            "version": "8.25.0",
+            "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.25.0.tgz",
+            "integrity": "sha512-TxRdQQLH4g7JkoFlYG3caW5v1S6kEkz8rqt80iQJZUYPq1zD1Ra7HfQBJJ88ABRaMvHAXnwRvRB4V+6sQ9xN5Q==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "@typescript-eslint/eslint-plugin": "8.25.0",
+                "@typescript-eslint/parser": "8.25.0",
+                "@typescript-eslint/utils": "8.25.0"
+            },
+            "engines": {
+                "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+            },
+            "funding": {
+                "type": "opencollective",
+                "url": "https://opencollective.com/typescript-eslint"
+            },
+            "peerDependencies": {
+                "eslint": "^8.57.0 || ^9.0.0",
+                "typescript": ">=4.8.4 <5.8.0"
+            }
+        },
         "node_modules/uc.micro": {
             "version": "2.1.0",
             "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
@@ -5104,11 +5729,29 @@
             "dev": true,
             "license": "MIT"
         },
+        "node_modules/undici": {
+            "version": "6.21.1",
+            "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.1.tgz",
+            "integrity": "sha512-q/1rj5D0/zayJB2FraXdaWxbhWiNKDvu8naDT2dl1yTlvJp4BLtOcp2a5BvgGNQpYYJzau7tf1WgKv3b+7mqpQ==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=18.17"
+            }
+        },
+        "node_modules/undici-types": {
+            "version": "6.20.0",
+            "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
+            "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
+            "dev": true,
+            "license": "MIT"
+        },
         "node_modules/uri-js": {
             "version": "4.4.1",
             "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
             "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
             "dev": true,
+            "license": "BSD-2-Clause",
             "dependencies": {
                 "punycode": "^2.1.0"
             }
@@ -5117,13 +5760,15 @@
             "version": "4.0.1",
             "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz",
             "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==",
-            "dev": true
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/util-deprecate": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
             "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
-            "dev": true
+            "dev": true,
+            "license": "MIT"
         },
         "node_modules/uuid": {
             "version": "8.3.2",
@@ -5139,6 +5784,7 @@
             "version": "8.2.0",
             "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz",
             "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==",
+            "license": "MIT",
             "engines": {
                 "node": ">=14.0.0"
             }
@@ -5147,6 +5793,7 @@
             "version": "9.0.1",
             "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz",
             "integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==",
+            "license": "MIT",
             "dependencies": {
                 "minimatch": "^5.1.0",
                 "semver": "^7.3.7",
@@ -5156,18 +5803,11 @@
                 "vscode": "^1.82.0"
             }
         },
-        "node_modules/vscode-languageclient/node_modules/brace-expansion": {
-            "version": "2.0.1",
-            "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
-            "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
-            "dependencies": {
-                "balanced-match": "^1.0.0"
-            }
-        },
         "node_modules/vscode-languageclient/node_modules/minimatch": {
             "version": "5.1.6",
             "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
             "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+            "license": "ISC",
             "dependencies": {
                 "brace-expansion": "^2.0.1"
             },
@@ -5179,6 +5819,7 @@
             "version": "3.17.5",
             "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz",
             "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==",
+            "license": "MIT",
             "dependencies": {
                 "vscode-jsonrpc": "8.2.0",
                 "vscode-languageserver-types": "3.17.5"
@@ -5187,13 +5828,38 @@
         "node_modules/vscode-languageserver-types": {
             "version": "3.17.5",
             "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz",
-            "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="
+            "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==",
+            "license": "MIT"
+        },
+        "node_modules/whatwg-encoding": {
+            "version": "3.1.1",
+            "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
+            "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "iconv-lite": "0.6.3"
+            },
+            "engines": {
+                "node": ">=18"
+            }
+        },
+        "node_modules/whatwg-mimetype": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
+            "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=18"
+            }
         },
         "node_modules/which": {
             "version": "2.0.2",
             "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
             "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
             "dev": true,
+            "license": "ISC",
             "dependencies": {
                 "isexe": "^2.0.0"
             },
@@ -5204,17 +5870,29 @@
                 "node": ">= 8"
             }
         },
+        "node_modules/word-wrap": {
+            "version": "1.2.5",
+            "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+            "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=0.10.0"
+            }
+        },
         "node_modules/wrap-ansi": {
-            "version": "7.0.0",
-            "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
-            "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+            "version": "8.1.0",
+            "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+            "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+            "dev": true,
+            "license": "MIT",
             "dependencies": {
-                "ansi-styles": "^4.0.0",
-                "string-width": "^4.1.0",
-                "strip-ansi": "^6.0.0"
+                "ansi-styles": "^6.1.0",
+                "string-width": "^5.0.1",
+                "strip-ansi": "^7.0.1"
             },
             "engines": {
-                "node": ">=10"
+                "node": ">=12"
             },
             "funding": {
                 "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
@@ -5239,11 +5917,107 @@
                 "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
             }
         },
+        "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": {
+            "version": "5.0.1",
+            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
+            "version": "4.3.0",
+            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+            "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "color-convert": "^2.0.1"
+            },
+            "engines": {
+                "node": ">=8"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+            }
+        },
+        "node_modules/wrap-ansi-cjs/node_modules/color-convert": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+            "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "color-name": "~1.1.4"
+            },
+            "engines": {
+                "node": ">=7.0.0"
+            }
+        },
+        "node_modules/wrap-ansi-cjs/node_modules/color-name": {
+            "version": "1.1.4",
+            "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+            "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+            "dev": true,
+            "license": "MIT"
+        },
+        "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
+            "version": "8.0.0",
+            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+            "dev": true,
+            "license": "MIT"
+        },
+        "node_modules/wrap-ansi-cjs/node_modules/string-width": {
+            "version": "4.2.3",
+            "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+            "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "emoji-regex": "^8.0.0",
+                "is-fullwidth-code-point": "^3.0.0",
+                "strip-ansi": "^6.0.1"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": {
+            "version": "6.0.1",
+            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+            "dev": true,
+            "license": "MIT",
+            "dependencies": {
+                "ansi-regex": "^5.0.1"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/wrap-ansi/node_modules/ansi-styles": {
+            "version": "6.2.1",
+            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+            "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+            "dev": true,
+            "license": "MIT",
+            "engines": {
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+            }
+        },
         "node_modules/wrappy": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
             "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
-            "dev": true
+            "dev": true,
+            "license": "ISC",
+            "optional": true
         },
         "node_modules/xml2js": {
             "version": "0.5.0",
@@ -5264,6 +6038,7 @@
             "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
             "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": ">=4.0"
             }
@@ -5272,6 +6047,7 @@
             "version": "5.0.8",
             "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
             "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+            "license": "ISC",
             "engines": {
                 "node": ">=10"
             }
@@ -5279,12 +6055,15 @@
         "node_modules/yallist": {
             "version": "4.0.0",
             "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-            "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+            "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+            "dev": true,
+            "license": "ISC"
         },
         "node_modules/yargs": {
             "version": "17.7.2",
             "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
             "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+            "license": "MIT",
             "dependencies": {
                 "cliui": "^8.0.1",
                 "escalade": "^3.1.1",
@@ -5302,15 +6081,58 @@
             "version": "21.1.1",
             "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
             "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+            "license": "ISC",
             "engines": {
                 "node": ">=12"
             }
         },
+        "node_modules/yargs/node_modules/ansi-regex": {
+            "version": "5.0.1",
+            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+            "license": "MIT",
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/yargs/node_modules/emoji-regex": {
+            "version": "8.0.0",
+            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+            "license": "MIT"
+        },
+        "node_modules/yargs/node_modules/string-width": {
+            "version": "4.2.3",
+            "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+            "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+            "license": "MIT",
+            "dependencies": {
+                "emoji-regex": "^8.0.0",
+                "is-fullwidth-code-point": "^3.0.0",
+                "strip-ansi": "^6.0.1"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/yargs/node_modules/strip-ansi": {
+            "version": "6.0.1",
+            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+            "license": "MIT",
+            "dependencies": {
+                "ansi-regex": "^5.0.1"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
         "node_modules/yauzl": {
             "version": "2.10.0",
             "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
             "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "buffer-crc32": "~0.2.3",
                 "fd-slicer": "~1.1.0"
@@ -5321,6 +6143,7 @@
             "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.5.1.tgz",
             "integrity": "sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==",
             "dev": true,
+            "license": "MIT",
             "dependencies": {
                 "buffer-crc32": "~0.2.3"
             }
@@ -5330,6 +6153,7 @@
             "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
             "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
             "dev": true,
+            "license": "MIT",
             "engines": {
                 "node": ">=10"
             },
diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json
index 3f09033051b..587ae92520b 100644
--- a/src/tools/rust-analyzer/editors/code/package.json
+++ b/src/tools/rust-analyzer/editors/code/package.json
@@ -7,6 +7,7 @@
     "version": "0.5.0-dev",
     "releaseTag": null,
     "publisher": "rust-lang",
+    "type": "commonjs",
     "repository": {
         "url": "https://github.com/rust-lang/rust-analyzer.git",
         "type": "git"
@@ -27,45 +28,51 @@
         }
     },
     "engines": {
-        "vscode": "^1.83.0"
+        "vscode": "^1.93.0"
     },
     "enabledApiProposals": [],
     "scripts": {
         "vscode:prepublish": "npm run build-base -- --minify",
         "package": "vsce package -o rust-analyzer.vsix",
-        "build-base": "esbuild ./src/main.ts --bundle --outfile=out/main.js --external:vscode --format=cjs --platform=node --target=node16",
+        "build-base": "esbuild ./src/main.ts --bundle --outfile=out/main.js --external:vscode --format=cjs --platform=node --target=node20",
         "build": "npm run build-base -- --sourcemap",
         "watch": "npm run build-base -- --sourcemap --watch",
-        "format": "prettier --write .",
-        "format:check": "prettier --check .",
-        "lint": "eslint -c .eslintrc.js --ext ts ./src ./tests",
+        "format": "node --experimental-strip-types node_modules/prettier/bin/prettier.cjs . --write",
+        "format:check": "node --experimental-strip-types node_modules/prettier/bin/prettier.cjs . --check",
+        "lint": "eslint .",
         "lint:fix": "npm run lint -- --fix",
         "typecheck": "tsc",
         "pretest": "npm run typecheck && npm run build",
         "test": "node ./out/tests/runTests.js"
     },
     "dependencies": {
-        "@hpcc-js/wasm": "^2.13.0",
-        "anser": "^2.1.1",
-        "d3": "^7.8.5",
-        "d3-graphviz": "^5.0.2",
+        "@hpcc-js/wasm": "^2.22.4",
+        "anser": "^2.3.2",
+        "d3": "^7.9.0",
+        "d3-graphviz": "^5.6.0",
+        "jiti": "^2.4.2",
         "vscode-languageclient": "^9.0.1"
     },
     "devDependencies": {
-        "@tsconfig/strictest": "^2.0.1",
-        "@types/node": "~16.11.7",
-        "@types/vscode": "~1.83",
-        "@typescript-eslint/eslint-plugin": "^6.0.0",
-        "@typescript-eslint/parser": "^6.0.0",
-        "@vscode/test-electron": "^2.3.8",
-        "@vscode/vsce": "^3.0.0",
+        "@eslint/js": "^9.21.0",
+        "@stylistic/eslint-plugin": "^4.1.0",
+        "@stylistic/eslint-plugin-js": "^4.1.0",
+        "@tsconfig/strictest": "^2.0.5",
+        "@types/node": "~22.13.4",
+        "@types/vscode": "~1.93.0",
+        "@typescript-eslint/eslint-plugin": "^8.25.0",
+        "@typescript-eslint/parser": "^8.25.0",
+        "@vscode/test-electron": "^2.4.1",
+        "@vscode/vsce": "^3.2.2",
         "esbuild": "^0.25.0",
-        "eslint": "^8.44.0",
-        "eslint-config-prettier": "^8.8.0",
-        "ovsx": "^0.8.2",
-        "prettier": "^3.0.0",
-        "tslib": "^2.6.0",
-        "typescript": "^5.6.0"
+        "eslint": "^9.21.0",
+        "eslint-config-prettier": "^10.0.2",
+        "eslint-define-config": "^2.1.0",
+        "ovsx": "0.10.1",
+        "prettier": "^3.5.2",
+        "tslib": "^2.8.1",
+        "typescript": "^5.7.3",
+        "typescript-eslint": "^8.25.0"
     },
     "activationEvents": [
         "workspaceContains:Cargo.toml",
@@ -1644,6 +1651,16 @@
             {
                 "title": "hover",
                 "properties": {
+                    "rust-analyzer.hover.dropGlue.enable": {
+                        "markdownDescription": "Whether to show drop glue information on hover.",
+                        "default": true,
+                        "type": "boolean"
+                    }
+                }
+            },
+            {
+                "title": "hover",
+                "properties": {
                     "rust-analyzer.hover.links.enable": {
                         "markdownDescription": "Use markdown syntax for links on hover.",
                         "default": true,
diff --git a/src/tools/rust-analyzer/editors/code/prettier.config.mts b/src/tools/rust-analyzer/editors/code/prettier.config.mts
new file mode 100644
index 00000000000..45cb3874eea
--- /dev/null
+++ b/src/tools/rust-analyzer/editors/code/prettier.config.mts
@@ -0,0 +1,12 @@
+import { type Config } from "prettier";
+
+const config: Config = {
+    // use 4 because it's Rustfmt's default
+    // https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#%5C34%20%5C%20%5C(default%5C)%5C%3A
+    tabWidth: 4,
+    // use 100 because it's Rustfmt's default
+    // https://rust-lang.github.io/rustfmt/?version=v1.4.38&search=#max_width
+    printWidth: 100,
+};
+
+export default config;
diff --git a/src/tools/rust-analyzer/editors/code/src/bootstrap.ts b/src/tools/rust-analyzer/editors/code/src/bootstrap.ts
index 8fc9f09324a..bccae73c9a7 100644
--- a/src/tools/rust-analyzer/editors/code/src/bootstrap.ts
+++ b/src/tools/rust-analyzer/editors/code/src/bootstrap.ts
@@ -177,9 +177,9 @@ async function hasToolchainFileWithRaDeclared(uri: vscode.Uri): Promise<boolean>
             await vscode.workspace.fs.readFile(uri),
         );
         return (
-            toolchainFileContents.match(/components\s*=\s*\[.*\"rust-analyzer\".*\]/g)?.length === 1
+            toolchainFileContents.match(/components\s*=\s*\[.*"rust-analyzer".*\]/g)?.length === 1
         );
-    } catch (e) {
+    } catch (_) {
         return false;
     }
 }
diff --git a/src/tools/rust-analyzer/editors/code/src/client.ts b/src/tools/rust-analyzer/editors/code/src/client.ts
index eac7b849fdb..cdeea7333a6 100644
--- a/src/tools/rust-analyzer/editors/code/src/client.ts
+++ b/src/tools/rust-analyzer/editors/code/src/client.ts
@@ -18,282 +18,263 @@ export async function createClient(
     config: Config,
     unlinkedFiles: vscode.Uri[],
 ): Promise<lc.LanguageClient> {
-    const clientOptions: lc.LanguageClientOptions = {
-        documentSelector: [{ scheme: "file", language: "rust" }],
-        initializationOptions,
-        diagnosticCollectionName: "rustc",
-        traceOutputChannel,
-        outputChannel,
-        middleware: {
-            workspace: {
-                // HACK: This is a workaround, when the client has been disposed, VSCode
-                // continues to emit events to the client and the default one for this event
-                // attempt to restart the client for no reason
-                async didChangeWatchedFile(event, next) {
-                    if (client.isRunning()) {
-                        await next(event);
-                    }
-                },
-                async configuration(
-                    params: lc.ConfigurationParams,
-                    token: vscode.CancellationToken,
-                    next: lc.ConfigurationRequest.HandlerSignature,
-                ) {
-                    const resp = await next(params, token);
-                    if (resp && Array.isArray(resp)) {
-                        return resp.map((val) => {
-                            return prepareVSCodeConfig(val);
-                        });
-                    } else {
-                        return resp;
-                    }
-                },
+    const raMiddleware: lc.Middleware = {
+        workspace: {
+            // HACK: This is a workaround, when the client has been disposed, VSCode
+            // continues to emit events to the client and the default one for this event
+            // attempt to restart the client for no reason
+            async didChangeWatchedFile(event, next) {
+                if (client.isRunning()) {
+                    await next(event);
+                }
             },
-            async handleDiagnostics(
-                uri: vscode.Uri,
-                diagnosticList: vscode.Diagnostic[],
-                next: lc.HandleDiagnosticsSignature,
+            async configuration(
+                params: lc.ConfigurationParams,
+                token: vscode.CancellationToken,
+                next: lc.ConfigurationRequest.HandlerSignature,
             ) {
-                const preview = config.previewRustcOutput;
-                const errorCode = config.useRustcErrorCode;
-                diagnosticList.forEach((diag, idx) => {
-                    const value =
-                        typeof diag.code === "string" || typeof diag.code === "number"
-                            ? diag.code
-                            : diag.code?.value;
-                    if (
-                        // FIXME: We currently emit this diagnostic way too early, before we have
-                        // loaded the project fully
-                        // value === "unlinked-file" &&
-                        value === "temporary-disabled" &&
-                        !unlinkedFiles.includes(uri) &&
-                        (diag.message === "file not included in crate hierarchy" ||
-                            diag.message.startsWith("This file is not included in any crates"))
-                    ) {
-                        const config = vscode.workspace.getConfiguration("rust-analyzer");
-                        if (config.get("showUnlinkedFileNotification")) {
-                            unlinkedFiles.push(uri);
-                            const folder = vscode.workspace.getWorkspaceFolder(uri)?.uri.fsPath;
-                            if (folder) {
-                                const parentBackslash = uri.fsPath.lastIndexOf(
-                                    pathSeparator + "src",
-                                );
-                                const parent = uri.fsPath.substring(0, parentBackslash);
+                const resp = await next(params, token);
+                if (resp && Array.isArray(resp)) {
+                    return resp.map((val) => {
+                        return prepareVSCodeConfig(val);
+                    });
+                } else {
+                    return resp;
+                }
+            },
+        },
+        async handleDiagnostics(
+            uri: vscode.Uri,
+            diagnosticList: vscode.Diagnostic[],
+            next: lc.HandleDiagnosticsSignature,
+        ) {
+            const preview = config.previewRustcOutput;
+            const errorCode = config.useRustcErrorCode;
+            diagnosticList.forEach((diag, idx) => {
+                const value =
+                    typeof diag.code === "string" || typeof diag.code === "number"
+                        ? diag.code
+                        : diag.code?.value;
+                if (
+                    // FIXME: We currently emit this diagnostic way too early, before we have
+                    // loaded the project fully
+                    // value === "unlinked-file" &&
+                    value === "temporary-disabled" &&
+                    !unlinkedFiles.includes(uri) &&
+                    (diag.message === "file not included in crate hierarchy" ||
+                        diag.message.startsWith("This file is not included in any crates"))
+                ) {
+                    const config = vscode.workspace.getConfiguration("rust-analyzer");
+                    if (config.get("showUnlinkedFileNotification")) {
+                        unlinkedFiles.push(uri);
+                        const folder = vscode.workspace.getWorkspaceFolder(uri)?.uri.fsPath;
+                        if (folder) {
+                            const parentBackslash = uri.fsPath.lastIndexOf(pathSeparator + "src");
+                            const parent = uri.fsPath.substring(0, parentBackslash);
 
-                                if (parent.startsWith(folder)) {
-                                    const path = vscode.Uri.file(
-                                        parent + pathSeparator + "Cargo.toml",
+                            if (parent.startsWith(folder)) {
+                                const path = vscode.Uri.file(parent + pathSeparator + "Cargo.toml");
+                                void vscode.workspace.fs.stat(path).then(async () => {
+                                    const choice = await vscode.window.showInformationMessage(
+                                        `This rust file does not belong to a loaded cargo project. It looks like it might belong to the workspace at ${path.path}, do you want to add it to the linked Projects?`,
+                                        "Yes",
+                                        "No",
+                                        "Don't show this again",
                                     );
-                                    void vscode.workspace.fs.stat(path).then(async () => {
-                                        const choice = await vscode.window.showInformationMessage(
-                                            `This rust file does not belong to a loaded cargo project. It looks like it might belong to the workspace at ${path.path}, do you want to add it to the linked Projects?`,
-                                            "Yes",
-                                            "No",
-                                            "Don't show this again",
-                                        );
-                                        switch (choice) {
-                                            case undefined:
-                                                break;
-                                            case "No":
-                                                break;
-                                            case "Yes":
-                                                const pathToInsert =
-                                                    "." +
-                                                    parent.substring(folder.length) +
-                                                    pathSeparator +
-                                                    "Cargo.toml";
-                                                await config.update(
-                                                    "linkedProjects",
-                                                    config
-                                                        .get<any[]>("linkedProjects")
-                                                        ?.concat(pathToInsert),
-                                                    false,
-                                                );
-                                                break;
-                                            case "Don't show this again":
-                                                await config.update(
-                                                    "showUnlinkedFileNotification",
-                                                    false,
-                                                    false,
-                                                );
-                                                break;
+                                    switch (choice) {
+                                        case undefined:
+                                            break;
+                                        case "No":
+                                            break;
+                                        case "Yes": {
+                                            const pathToInsert =
+                                                "." +
+                                                parent.substring(folder.length) +
+                                                pathSeparator +
+                                                "Cargo.toml";
+                                            const value = config
+                                                // eslint-disable-next-line @typescript-eslint/no-explicit-any
+                                                .get<any[]>("linkedProjects")
+                                                ?.concat(pathToInsert);
+                                            await config.update("linkedProjects", value, false);
+                                            break;
                                         }
-                                    });
-                                }
+                                        case "Don't show this again":
+                                            await config.update(
+                                                "showUnlinkedFileNotification",
+                                                false,
+                                                false,
+                                            );
+                                            break;
+                                    }
+                                });
                             }
                         }
                     }
+                }
 
-                    // Abuse the fact that VSCode leaks the LSP diagnostics data field through the
-                    // Diagnostic class, if they ever break this we are out of luck and have to go
-                    // back to the worst diagnostics experience ever:)
+                // Abuse the fact that VSCode leaks the LSP diagnostics data field through the
+                // Diagnostic class, if they ever break this we are out of luck and have to go
+                // back to the worst diagnostics experience ever:)
 
-                    // We encode the rendered output of a rustc diagnostic in the rendered field of
-                    // the data payload of the lsp diagnostic. If that field exists, overwrite the
-                    // diagnostic code such that clicking it opens the diagnostic in a readonly
-                    // text editor for easy inspection
-                    const rendered = (diag as unknown as { data?: { rendered?: string } }).data
-                        ?.rendered;
-                    if (rendered) {
-                        if (preview) {
-                            const decolorized = anser.ansiToText(rendered);
-                            const index =
-                                decolorized.match(/^(note|help):/m)?.index || rendered.length;
-                            diag.message = decolorized
-                                .substring(0, index)
-                                .replace(/^ -->[^\n]+\n/m, "");
-                        }
-                        diag.code = {
-                            target: vscode.Uri.from({
-                                scheme: diagnostics.URI_SCHEME,
-                                path: `/diagnostic message [${idx.toString()}]`,
-                                fragment: uri.toString(),
-                                query: idx.toString(),
-                            }),
-                            value:
-                                errorCode && value ? value : "Click for full compiler diagnostic",
-                        };
+                // We encode the rendered output of a rustc diagnostic in the rendered field of
+                // the data payload of the lsp diagnostic. If that field exists, overwrite the
+                // diagnostic code such that clicking it opens the diagnostic in a readonly
+                // text editor for easy inspection
+                const rendered = (diag as unknown as { data?: { rendered?: string } }).data
+                    ?.rendered;
+                if (rendered) {
+                    if (preview) {
+                        const decolorized = anser.ansiToText(rendered);
+                        const index = decolorized.match(/^(note|help):/m)?.index || rendered.length;
+                        diag.message = decolorized
+                            .substring(0, index)
+                            .replace(/^ -->[^\n]+\n/m, "");
                     }
-                });
-                return next(uri, diagnosticList);
-            },
-            async provideHover(
-                document: vscode.TextDocument,
-                position: vscode.Position,
-                token: vscode.CancellationToken,
-                _next: lc.ProvideHoverSignature,
-            ) {
-                const editor = vscode.window.activeTextEditor;
-                const positionOrRange = editor?.selection?.contains(position)
-                    ? client.code2ProtocolConverter.asRange(editor.selection)
-                    : client.code2ProtocolConverter.asPosition(position);
-                return client
-                    .sendRequest(
-                        ra.hover,
-                        {
-                            textDocument:
-                                client.code2ProtocolConverter.asTextDocumentIdentifier(document),
-                            position: positionOrRange,
-                        },
-                        token,
-                    )
-                    .then(
-                        (result) => {
-                            if (!result) return null;
-                            const hover = client.protocol2CodeConverter.asHover(result);
-                            if (!!result.actions) {
-                                hover.contents.push(renderHoverActions(result.actions));
-                            }
-                            return hover;
-                        },
-                        (error) => {
-                            client.handleFailedRequest(lc.HoverRequest.type, token, error, null);
-                            return Promise.resolve(null);
-                        },
+                    diag.code = {
+                        target: vscode.Uri.from({
+                            scheme: diagnostics.URI_SCHEME,
+                            path: `/diagnostic message [${idx.toString()}]`,
+                            fragment: uri.toString(),
+                            query: idx.toString(),
+                        }),
+                        value: errorCode && value ? value : "Click for full compiler diagnostic",
+                    };
+                }
+            });
+            return next(uri, diagnosticList);
+        },
+        async provideHover(
+            document: vscode.TextDocument,
+            position: vscode.Position,
+            token: vscode.CancellationToken,
+            _next: lc.ProvideHoverSignature,
+        ) {
+            const editor = vscode.window.activeTextEditor;
+            const positionOrRange = editor?.selection?.contains(position)
+                ? client.code2ProtocolConverter.asRange(editor.selection)
+                : client.code2ProtocolConverter.asPosition(position);
+            const params = {
+                textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
+                position: positionOrRange,
+            };
+            return client.sendRequest(ra.hover, params, token).then(
+                (result) => {
+                    if (!result) return null;
+                    const hover = client.protocol2CodeConverter.asHover(result);
+                    if (result.actions) {
+                        hover.contents.push(renderHoverActions(result.actions));
+                    }
+                    return hover;
+                },
+                (error) => {
+                    client.handleFailedRequest(lc.HoverRequest.type, token, error, null);
+                    return Promise.resolve(null);
+                },
+            );
+        },
+        // Using custom handling of CodeActions to support action groups and snippet edits.
+        // Note that this means we have to re-implement lazy edit resolving ourselves as well.
+        async provideCodeActions(
+            document: vscode.TextDocument,
+            range: vscode.Range,
+            context: vscode.CodeActionContext,
+            token: vscode.CancellationToken,
+            _next: lc.ProvideCodeActionsSignature,
+        ) {
+            const params: lc.CodeActionParams = {
+                textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
+                range: client.code2ProtocolConverter.asRange(range),
+                context: await client.code2ProtocolConverter.asCodeActionContext(context, token),
+            };
+            const callback = async (
+                values: (lc.Command | lc.CodeAction)[] | null,
+            ): Promise<(vscode.Command | vscode.CodeAction)[] | undefined> => {
+                if (values === null) return undefined;
+                const result: (vscode.CodeAction | vscode.Command)[] = [];
+                const groups = new Map<string, { index: number; items: vscode.CodeAction[] }>();
+                for (const item of values) {
+                    // In our case we expect to get code edits only from diagnostics
+                    if (lc.CodeAction.is(item)) {
+                        assert(!item.command, "We don't expect to receive commands in CodeActions");
+                        const action = await client.protocol2CodeConverter.asCodeAction(
+                            item,
+                            token,
+                        );
+                        result.push(action);
+                        continue;
+                    }
+                    assert(
+                        isCodeActionWithoutEditsAndCommands(item),
+                        "We don't expect edits or commands here",
                     );
-            },
-            // Using custom handling of CodeActions to support action groups and snippet edits.
-            // Note that this means we have to re-implement lazy edit resolving ourselves as well.
-            async provideCodeActions(
-                document: vscode.TextDocument,
-                range: vscode.Range,
-                context: vscode.CodeActionContext,
-                token: vscode.CancellationToken,
-                _next: lc.ProvideCodeActionsSignature,
-            ) {
-                const params: lc.CodeActionParams = {
-                    textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document),
-                    range: client.code2ProtocolConverter.asRange(range),
-                    context: await client.code2ProtocolConverter.asCodeActionContext(
-                        context,
-                        token,
-                    ),
-                };
-                return client.sendRequest(lc.CodeActionRequest.type, params, token).then(
-                    async (values) => {
-                        if (values === null) return undefined;
-                        const result: (vscode.CodeAction | vscode.Command)[] = [];
-                        const groups = new Map<
-                            string,
-                            { index: number; items: vscode.CodeAction[] }
-                        >();
-                        for (const item of values) {
-                            // In our case we expect to get code edits only from diagnostics
-                            if (lc.CodeAction.is(item)) {
-                                assert(
-                                    !item.command,
-                                    "We don't expect to receive commands in CodeActions",
-                                );
-                                const action = await client.protocol2CodeConverter.asCodeAction(
-                                    item,
-                                    token,
-                                );
-                                result.push(action);
-                                continue;
-                            }
-                            assert(
-                                isCodeActionWithoutEditsAndCommands(item),
-                                "We don't expect edits or commands here",
-                            );
-                            const kind = client.protocol2CodeConverter.asCodeActionKind(
-                                (item as any).kind,
-                            );
-                            const action = new vscode.CodeAction(item.title, kind);
-                            const group = (item as any).group;
-                            action.command = {
-                                command: "rust-analyzer.resolveCodeAction",
-                                title: item.title,
-                                arguments: [item],
-                            };
+                    // eslint-disable-next-line @typescript-eslint/no-explicit-any
+                    const kind = client.protocol2CodeConverter.asCodeActionKind((item as any).kind);
+                    const action = new vscode.CodeAction(item.title, kind);
+                    // eslint-disable-next-line @typescript-eslint/no-explicit-any
+                    const group = (item as any).group;
+                    action.command = {
+                        command: "rust-analyzer.resolveCodeAction",
+                        title: item.title,
+                        arguments: [item],
+                    };
 
-                            // Set a dummy edit, so that VS Code doesn't try to resolve this.
-                            action.edit = new WorkspaceEdit();
+                    // Set a dummy edit, so that VS Code doesn't try to resolve this.
+                    action.edit = new WorkspaceEdit();
 
-                            if (group) {
-                                let entry = groups.get(group);
-                                if (!entry) {
-                                    entry = { index: result.length, items: [] };
-                                    groups.set(group, entry);
-                                    result.push(action);
-                                }
-                                entry.items.push(action);
-                            } else {
-                                result.push(action);
-                            }
+                    if (group) {
+                        let entry = groups.get(group);
+                        if (!entry) {
+                            entry = { index: result.length, items: [] };
+                            groups.set(group, entry);
+                            result.push(action);
                         }
-                        for (const [group, { index, items }] of groups) {
-                            if (items.length === 1) {
-                                const item = unwrapUndefinable(items[0]);
-                                result[index] = item;
-                            } else {
-                                const action = new vscode.CodeAction(group);
-                                const item = unwrapUndefinable(items[0]);
-                                action.kind = item.kind;
-                                action.command = {
-                                    command: "rust-analyzer.applyActionGroup",
-                                    title: "",
-                                    arguments: [
-                                        items.map((item) => {
-                                            return {
-                                                label: item.title,
-                                                arguments: item.command!.arguments![0],
-                                            };
-                                        }),
-                                    ],
-                                };
+                        entry.items.push(action);
+                    } else {
+                        result.push(action);
+                    }
+                }
+                for (const [group, { index, items }] of groups) {
+                    if (items.length === 1) {
+                        const item = unwrapUndefinable(items[0]);
+                        result[index] = item;
+                    } else {
+                        const action = new vscode.CodeAction(group);
+                        const item = unwrapUndefinable(items[0]);
+                        action.kind = item.kind;
+                        action.command = {
+                            command: "rust-analyzer.applyActionGroup",
+                            title: "",
+                            arguments: [
+                                items.map((item) => {
+                                    return {
+                                        label: item.title,
+                                        arguments: item.command!.arguments![0],
+                                    };
+                                }),
+                            ],
+                        };
 
-                                // Set a dummy edit, so that VS Code doesn't try to resolve this.
-                                action.edit = new WorkspaceEdit();
+                        // Set a dummy edit, so that VS Code doesn't try to resolve this.
+                        action.edit = new WorkspaceEdit();
 
-                                result[index] = action;
-                            }
-                        }
-                        return result;
-                    },
-                    (_error) => undefined,
-                );
-            },
+                        result[index] = action;
+                    }
+                }
+                return result;
+            };
+            return client
+                .sendRequest(lc.CodeActionRequest.type, params, token)
+                .then(callback, (_error) => undefined);
         },
+    };
+    const clientOptions: lc.LanguageClientOptions = {
+        documentSelector: [{ scheme: "file", language: "rust" }],
+        initializationOptions,
+        diagnosticCollectionName: "rustc",
+        traceOutputChannel,
+        outputChannel,
+        middleware: raMiddleware,
         markdown: {
             supportHtml: true,
         },
@@ -319,9 +300,11 @@ class ExperimentalFeatures implements lc.StaticFeature {
     constructor(config: Config) {
         this.testExplorer = config.testExplorer || false;
     }
+
     getState(): lc.FeatureState {
         return { kind: "static" };
     }
+
     fillClientCapabilities(capabilities: lc.ClientCapabilities): void {
         capabilities.experimental = {
             snippetTextEdit: true,
@@ -345,11 +328,14 @@ class ExperimentalFeatures implements lc.StaticFeature {
             ...capabilities.experimental,
         };
     }
+
     initialize(
         _capabilities: lc.ServerCapabilities,
         _documentSelector: lc.DocumentSelector | undefined,
     ): void {}
+
     dispose(): void {}
+
     clear(): void {}
 }
 
@@ -357,6 +343,7 @@ class OverrideFeatures implements lc.StaticFeature {
     getState(): lc.FeatureState {
         return { kind: "static" };
     }
+
     fillClientCapabilities(capabilities: lc.ClientCapabilities): void {
         // Force disable `augmentsSyntaxTokens`, VSCode's textmate grammar is somewhat incomplete
         // making the experience generally worse
@@ -365,14 +352,18 @@ class OverrideFeatures implements lc.StaticFeature {
             caps.augmentsSyntaxTokens = false;
         }
     }
+
     initialize(
         _capabilities: lc.ServerCapabilities,
         _documentSelector: lc.DocumentSelector | undefined,
     ): void {}
+
     dispose(): void {}
+
     clear(): void {}
 }
 
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
 function isCodeActionWithoutEditsAndCommands(value: any): boolean {
     const candidate: lc.CodeAction = value;
     return (
diff --git a/src/tools/rust-analyzer/editors/code/src/commands.ts b/src/tools/rust-analyzer/editors/code/src/commands.ts
index eee623ecae9..4e614d32057 100644
--- a/src/tools/rust-analyzer/editors/code/src/commands.ts
+++ b/src/tools/rust-analyzer/editors/code/src/commands.ts
@@ -78,6 +78,7 @@ export function memoryUsage(ctx: CtxInit): Cmd {
         provideTextDocumentContent(_uri: vscode.Uri): vscode.ProviderResult<string> {
             if (!vscode.window.activeTextEditor) return "";
 
+            // eslint-disable-next-line @typescript-eslint/no-explicit-any
             return ctx.client.sendRequest(ra.memoryUsage).then((mem: any) => {
                 return "Per-query memory usage:\n" + mem + "\n(note: database has been cleared)";
             });
@@ -161,7 +162,7 @@ export function joinLines(ctx: CtxInit): Cmd {
         });
         const textEdits = await client.protocol2CodeConverter.asTextEdits(items);
         await editor.edit((builder) => {
-            textEdits.forEach((edit: any) => {
+            textEdits.forEach((edit: vscode.TextEdit) => {
                 builder.replace(edit.range, edit.newText);
             });
         });
@@ -209,6 +210,7 @@ export function onEnter(ctx: CtxInit): Cmd {
                 ),
                 position: client.code2ProtocolConverter.asPosition(editor.selection.active),
             })
+            // eslint-disable-next-line @typescript-eslint/no-explicit-any
             .catch((_error: any) => {
                 // client.handleFailedRequest(OnEnterRequest.type, error, null);
                 return null;
@@ -528,6 +530,7 @@ function viewFileUsingTextDocumentContentProvider(
                 void sleep(10).then(() => this.eventEmitter.fire(this.uri));
             }
         }
+
         private onDidChangeActiveTextEditor(editor: vscode.TextEditor | undefined) {
             if (editor && isRustEditor(editor) && shouldUpdate) {
                 this.eventEmitter.fire(this.uri);
@@ -620,6 +623,7 @@ export function viewFileText(ctx: CtxInit): Cmd {
                 void sleep(10).then(() => this.eventEmitter.fire(this.uri));
             }
         }
+
         private onDidChangeActiveTextEditor(editor: vscode.TextEditor | undefined) {
             if (editor && isRustEditor(editor)) {
                 this.eventEmitter.fire(this.uri);
@@ -683,6 +687,7 @@ export function viewItemTree(ctx: CtxInit): Cmd {
                 void sleep(10).then(() => this.eventEmitter.fire(this.uri));
             }
         }
+
         private onDidChangeActiveTextEditor(editor: vscode.TextEditor | undefined) {
             if (editor && isRustEditor(editor)) {
                 this.eventEmitter.fire(this.uri);
@@ -1001,9 +1006,8 @@ export function resolveCodeAction(ctx: CtxInit): Cmd {
             ...itemEdit,
             documentChanges: itemEdit.documentChanges?.filter((change) => "kind" in change),
         };
-        const fileSystemEdit = await client.protocol2CodeConverter.asWorkspaceEdit(
-            lcFileSystemEdit,
-        );
+        const fileSystemEdit =
+            await client.protocol2CodeConverter.asWorkspaceEdit(lcFileSystemEdit);
         await vscode.workspace.applyEdit(fileSystemEdit);
 
         // replace all text edits so that we can convert snippet text edits into `vscode.SnippetTextEdit`s
diff --git a/src/tools/rust-analyzer/editors/code/src/config.ts b/src/tools/rust-analyzer/editors/code/src/config.ts
index d1467a4e824..2ae32913452 100644
--- a/src/tools/rust-analyzer/editors/code/src/config.ts
+++ b/src/tools/rust-analyzer/editors/code/src/config.ts
@@ -13,12 +13,7 @@ export type RunnableEnvCfgItem = {
 };
 export type RunnableEnvCfg = Record<string, string> | RunnableEnvCfgItem[];
 
-type ShowStatusBar =
-    | "always"
-    | "never"
-    | {
-          documentSelector: vscode.DocumentSelector;
-      };
+type ShowStatusBar = "always" | "never" | { documentSelector: vscode.DocumentSelector };
 
 export class Config {
     readonly extensionId = "rust-lang.rust-analyzer";
@@ -145,13 +140,13 @@ export class Config {
                 {
                     // Parent doc single-line comment
                     // e.g. //!|
-                    beforeText: /^\s*\/{2}\!.*$/,
+                    beforeText: /^\s*\/{2}!.*$/,
                     action: { indentAction, appendText: "//! " },
                 },
                 {
                     // Begins an auto-closed multi-line comment (standard or parent doc)
                     // e.g. /** | */ or /*! | */
-                    beforeText: /^\s*\/\*(\*|\!)(?!\/)([^\*]|\*(?!\/))*$/,
+                    beforeText: /^\s*\/\*(\*|!)(?!\/)([^*]|\*(?!\/))*$/,
                     afterText: /^\s*\*\/$/,
                     action: {
                         indentAction: vscode.IndentAction.IndentOutdent,
@@ -161,19 +156,19 @@ export class Config {
                 {
                     // Begins a multi-line comment (standard or parent doc)
                     // e.g. /** ...| or /*! ...|
-                    beforeText: /^\s*\/\*(\*|\!)(?!\/)([^\*]|\*(?!\/))*$/,
+                    beforeText: /^\s*\/\*(\*|!)(?!\/)([^*]|\*(?!\/))*$/,
                     action: { indentAction, appendText: " * " },
                 },
                 {
                     // Continues a multi-line comment
                     // e.g.  * ...|
-                    beforeText: /^(\ \ )*\ \*(\ ([^\*]|\*(?!\/))*)?$/,
+                    beforeText: /^( {2})* \*( ([^*]|\*(?!\/))*)?$/,
                     action: { indentAction, appendText: "* " },
                 },
                 {
                     // Dedents after closing a multi-line comment
                     // e.g.  */|
-                    beforeText: /^(\ \ )*\ \*\/\s*$/,
+                    beforeText: /^( {2})* \*\/\s*$/,
                     action: { indentAction, removeText: 1 },
                 },
             ];
@@ -227,9 +222,11 @@ export class Config {
             ),
         );
     }
+
     get checkOnSave() {
         return this.get<boolean>("checkOnSave") ?? false;
     }
+
     async toggleCheckOnSave() {
         const config = this.cfg.inspect<boolean>("checkOnSave") ?? { key: "checkOnSave" };
         let overrideInLanguage;
@@ -269,8 +266,10 @@ export class Config {
     }
 
     runnablesExtraEnv(label: string): Record<string, string> | undefined {
+        // eslint-disable-next-line @typescript-eslint/no-explicit-any
         const item = this.get<any>("runnables.extraEnv") ?? this.get<any>("runnableEnv");
         if (!item) return undefined;
+        // eslint-disable-next-line @typescript-eslint/no-explicit-any
         const fixRecord = (r: Record<string, any>) => {
             for (const key in r) {
                 if (typeof r[key] !== "string") {
@@ -339,6 +338,7 @@ export class Config {
             gotoTypeDef: this.get<boolean>("hover.actions.gotoTypeDef.enable"),
         };
     }
+
     get previewRustcOutput() {
         return this.get<boolean>("diagnostics.previewRustcOutput");
     }
@@ -370,6 +370,7 @@ export class Config {
     get askBeforeUpdateTest() {
         return this.get<boolean>("runnables.askBeforeUpdateTest");
     }
+
     async setAskBeforeUpdateTest(value: boolean) {
         await this.cfg.update("runnables.askBeforeUpdateTest", value, true);
     }
@@ -378,11 +379,13 @@ export class Config {
 export function prepareVSCodeConfig<T>(resp: T): T {
     if (Is.string(resp)) {
         return substituteVSCodeVariableInString(resp) as T;
+        // eslint-disable-next-line @typescript-eslint/no-explicit-any
     } else if (resp && Is.array<any>(resp)) {
         return resp.map((val) => {
             return prepareVSCodeConfig(val);
         }) as T;
     } else if (resp && typeof resp === "object") {
+        // eslint-disable-next-line @typescript-eslint/no-explicit-any
         const res: { [key: string]: any } = {};
         for (const key in resp) {
             const val = resp[key];
@@ -489,8 +492,7 @@ function computeVscodeVar(varName: string): string | null {
         // TODO: support for remote workspaces?
         const fsPath: string =
             folder === undefined
-                ? // no workspace opened
-                  ""
+                ? "" // no workspace opened
                 : // could use currently opened document to detect the correct
                   // workspace. However, that would be determined by the document
                   // user has opened on Editor startup. Could lead to
diff --git a/src/tools/rust-analyzer/editors/code/src/ctx.ts b/src/tools/rust-analyzer/editors/code/src/ctx.ts
index 4248305d5cc..ac73f2ae6bf 100644
--- a/src/tools/rust-analyzer/editors/code/src/ctx.ts
+++ b/src/tools/rust-analyzer/editors/code/src/ctx.ts
@@ -34,13 +34,8 @@ import type { RustAnalyzerExtensionApi } from "./main";
 
 export type Workspace =
     | { kind: "Empty" }
-    | {
-          kind: "Workspace Folder";
-      }
-    | {
-          kind: "Detached Files";
-          files: vscode.TextDocument[];
-      };
+    | { kind: "Workspace Folder" }
+    | { kind: "Detached Files"; files: vscode.TextDocument[] };
 
 export function fetchWorkspace(): Workspace {
     const folders = (vscode.workspace.workspaceFolders || []).filter(
@@ -53,10 +48,7 @@ export function fetchWorkspace(): Workspace {
     return folders.length === 0
         ? rustDocuments.length === 0
             ? { kind: "Empty" }
-            : {
-                  kind: "Detached Files",
-                  files: rustDocuments,
-              }
+            : { kind: "Detached Files", files: rustDocuments }
         : { kind: "Workspace Folder" };
 }
 
@@ -89,6 +81,7 @@ export class Ctx implements RustAnalyzerExtensionApi {
     private _dependencyTreeView:
         | vscode.TreeView<Dependency | DependencyFile | DependencyId>
         | undefined;
+
     private _syntaxTreeProvider: SyntaxTreeProvider | undefined;
     private _syntaxTreeView: vscode.TreeView<SyntaxElement> | undefined;
     private lastStatus: ServerStatusParams | { health: "stopped" } = { health: "stopped" };
@@ -267,7 +260,7 @@ export class Ctx implements RustAnalyzerExtensionApi {
             let message = "bootstrap error. ";
 
             message +=
-                'See the logs in "OUTPUT > Rust Analyzer Client" (should open automatically). ';
+                'See the logs in "OUTPUT > Rust Analyzer Client" (should open automatically).';
             message +=
                 'To enable verbose logs, click the gear icon in the "OUTPUT" tab and select "Debug".';
 
@@ -476,9 +469,11 @@ export class Ctx implements RustAnalyzerExtensionApi {
         this.lastStatus = status;
         this.updateStatusBarItem();
     }
+
     refreshServerStatus() {
         this.updateStatusBarItem();
     }
+
     private updateStatusBarItem() {
         let icon = "";
         const status = this.lastStatus;
@@ -533,19 +528,14 @@ export class Ctx implements RustAnalyzerExtensionApi {
 
         const toggleCheckOnSave = this.config.checkOnSave ? "Disable" : "Enable";
         statusBar.tooltip.appendMarkdown(
-            `[Extension Info](command:rust-analyzer.serverVersion "Show version and server binary info"): Version ${this.version}, Server Version ${this._serverVersion}` +
-                "\n\n---\n\n" +
-                '[$(terminal) Open Logs](command:rust-analyzer.openLogs "Open the server logs")' +
-                "\n\n" +
-                `[$(settings) ${toggleCheckOnSave} Check on Save](command:rust-analyzer.toggleCheckOnSave "Temporarily ${toggleCheckOnSave.toLowerCase()} check on save functionality")` +
-                "\n\n" +
-                '[$(refresh) Reload Workspace](command:rust-analyzer.reloadWorkspace "Reload and rediscover workspaces")' +
-                "\n\n" +
-                '[$(symbol-property) Rebuild Build Dependencies](command:rust-analyzer.rebuildProcMacros "Rebuild build scripts and proc-macros")' +
-                "\n\n" +
-                '[$(stop-circle) Stop server](command:rust-analyzer.stopServer "Stop the server")' +
-                "\n\n" +
-                '[$(debug-restart) Restart server](command:rust-analyzer.restartServer "Restart the server")',
+            `[Extension Info](command:rust-analyzer.serverVersion "Show version and server binary info"): Version ${this.version}, Server Version ${this._serverVersion}\n\n` +
+                `---\n\n` +
+                `[$(terminal) Open Logs](command:rust-analyzer.openLogs "Open the server logs")\n\n` +
+                `[$(settings) ${toggleCheckOnSave} Check on Save](command:rust-analyzer.toggleCheckOnSave "Temporarily ${toggleCheckOnSave.toLowerCase()} check on save functionality")\n\n` +
+                `[$(refresh) Reload Workspace](command:rust-analyzer.reloadWorkspace "Reload and rediscover workspaces")\n\n` +
+                `[$(symbol-property) Rebuild Build Dependencies](command:rust-analyzer.rebuildProcMacros "Rebuild build scripts and proc-macros")\n\n` +
+                `[$(stop-circle) Stop server](command:rust-analyzer.stopServer "Stop the server")\n\n` +
+                `[$(debug-restart) Restart server](command:rust-analyzer.restartServer "Restart the server")`,
         );
         if (!status.quiescent) icon = "$(loading~spin) ";
         statusBar.text = `${icon}rust-analyzer`;
@@ -580,4 +570,5 @@ export interface Disposable {
     dispose(): void;
 }
 
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
 export type Cmd = (...args: any[]) => unknown;
diff --git a/src/tools/rust-analyzer/editors/code/src/debug.ts b/src/tools/rust-analyzer/editors/code/src/debug.ts
index f21ca2e8f96..72a9aabc043 100644
--- a/src/tools/rust-analyzer/editors/code/src/debug.ts
+++ b/src/tools/rust-analyzer/editors/code/src/debug.ts
@@ -22,6 +22,7 @@ export async function makeDebugConfig(ctx: Ctx, runnable: ra.Runnable): Promise<
     if (!debugConfig) return;
 
     const wsLaunchSection = vscode.workspace.getConfiguration("launch", scope);
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
     const configurations = wsLaunchSection.get<any[]>("configurations") || [];
 
     const index = configurations.findIndex((c) => c.name === debugConfig.name);
@@ -46,6 +47,7 @@ export async function startDebugSession(ctx: Ctx, runnable: ra.Runnable): Promis
     let message = "";
 
     const wsLaunchSection = vscode.workspace.getConfiguration("launch");
+    // eslint-disable-next-line @typescript-eslint/no-explicit-any
     const configurations = wsLaunchSection.get<any[]>("configurations") || [];
 
     // The runnable label is the name of the test with the "test prefix"
@@ -121,7 +123,7 @@ async function getDebugConfiguration(
         debugOutput.show(true);
     }
     // folder exists or RA is not active.
-    // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
+
     const workspaceFolders = vscode.workspace.workspaceFolders!;
     const isMultiFolderWorkspace = workspaceFolders.length > 1;
     const firstWorkspace = workspaceFolders[0];
@@ -189,8 +191,9 @@ async function getDebugConfiguration(
         sourceFileMap,
     );
     if (debugConfig.type in debugOptions.engineSettings) {
+        // eslint-disable-next-line @typescript-eslint/no-explicit-any
         const settingsMap = (debugOptions.engineSettings as any)[debugConfig.type];
-        for (var key in settingsMap) {
+        for (const key in settingsMap) {
             debugConfig[key] = settingsMap[key];
         }
     }
@@ -409,7 +412,7 @@ function quote(xs: string[]) {
                 return "'" + s.replace(/(['\\])/g, "\\$1") + "'";
             }
             if (/["'\s]/.test(s)) {
-                return '"' + s.replace(/(["\\$`!])/g, "\\$1") + '"';
+                return `"${s.replace(/(["\\$`!])/g, "\\$1")}"`;
             }
             return s.replace(/([A-Za-z]:)?([#!"$&'()*,:;<=>?@[\\\]^`{|}])/g, "$1\\$2");
         })
diff --git a/src/tools/rust-analyzer/editors/code/src/diagnostics.ts b/src/tools/rust-analyzer/editors/code/src/diagnostics.ts
index 9fb2993d12f..cd0e43b2120 100644
--- a/src/tools/rust-analyzer/editors/code/src/diagnostics.ts
+++ b/src/tools/rust-analyzer/editors/code/src/diagnostics.ts
@@ -104,10 +104,7 @@ export class AnsiDecorationProvider implements vscode.Disposable {
 
         for (const [lineNumber, line] of lines.entries()) {
             const totalEscapeLength = 0;
-
-            // eslint-disable-next-line camelcase
             const parsed = anser.ansiToJson(line, { use_classes: true });
-
             let offset = 0;
 
             for (const span of parsed) {
@@ -162,23 +159,23 @@ export class AnsiDecorationProvider implements vscode.Disposable {
     // NOTE: This could just be a kebab-case to camelCase conversion, but I think it's
     // a short enough list to just write these by hand
     static readonly _anserToThemeColor: Record<string, ThemeColor> = {
-        "ansi-black": "ansiBlack",
-        "ansi-white": "ansiWhite",
-        "ansi-red": "ansiRed",
-        "ansi-green": "ansiGreen",
-        "ansi-yellow": "ansiYellow",
-        "ansi-blue": "ansiBlue",
-        "ansi-magenta": "ansiMagenta",
-        "ansi-cyan": "ansiCyan",
-
-        "ansi-bright-black": "ansiBrightBlack",
-        "ansi-bright-white": "ansiBrightWhite",
-        "ansi-bright-red": "ansiBrightRed",
-        "ansi-bright-green": "ansiBrightGreen",
-        "ansi-bright-yellow": "ansiBrightYellow",
-        "ansi-bright-blue": "ansiBrightBlue",
-        "ansi-bright-magenta": "ansiBrightMagenta",
-        "ansi-bright-cyan": "ansiBrightCyan",
+        "ansi-black": new ThemeColor("terminal.ansiBlack"),
+        "ansi-white": new ThemeColor("terminal.ansiWhite"),
+        "ansi-red": new ThemeColor("terminal.ansiRed"),
+        "ansi-green": new ThemeColor("terminal.ansiGreen"),
+        "ansi-yellow": new ThemeColor("terminal.ansiYellow"),
+        "ansi-blue": new ThemeColor("terminal.ansiBlue"),
+        "ansi-magenta": new ThemeColor("terminal.ansiMagenta"),
+        "ansi-cyan": new ThemeColor("terminal.ansiCyan"),
+
+        "ansi-bright-black": new ThemeColor("terminal.ansiBrightBlack"),
+        "ansi-bright-white": new ThemeColor("terminal.ansiBrightWhite"),
+        "ansi-bright-red": new ThemeColor("terminal.ansiBrightRed"),
+        "ansi-bright-green": new ThemeColor("terminal.ansiBrightGreen"),
+        "ansi-bright-yellow": new ThemeColor("terminal.ansiBrightYellow"),
+        "ansi-bright-blue": new ThemeColor("terminal.ansiBrightBlue"),
+        "ansi-bright-magenta": new ThemeColor("terminal.ansiBrightMagenta"),
+        "ansi-bright-cyan": new ThemeColor("terminal.ansiBrightCyan"),
     };
 
     private static _convertColor(
@@ -210,11 +207,6 @@ export class AnsiDecorationProvider implements vscode.Disposable {
             }
         }
 
-        const themeColor = AnsiDecorationProvider._anserToThemeColor[color];
-        if (themeColor) {
-            return new ThemeColor("terminal." + themeColor);
-        }
-
-        return undefined;
+        return AnsiDecorationProvider._anserToThemeColor[color];
     }
 }
diff --git a/src/tools/rust-analyzer/editors/code/src/lang_client.ts b/src/tools/rust-analyzer/editors/code/src/lang_client.ts
index 09d64efc048..dc448f554c5 100644
--- a/src/tools/rust-analyzer/editors/code/src/lang_client.ts
+++ b/src/tools/rust-analyzer/editors/code/src/lang_client.ts
@@ -5,6 +5,8 @@ export class RaLanguageClient extends lc.LanguageClient {
     override handleFailedRequest<T>(
         type: lc.MessageSignature,
         token: vscode.CancellationToken | undefined,
+        // declared as `any` in vscode-languageclient
+        // eslint-disable-next-line @typescript-eslint/no-explicit-any
         error: any,
         defaultValue: T,
         showNotification?: boolean | undefined,
diff --git a/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts b/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts
index af86d9efd14..af5129ac963 100644
--- a/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts
+++ b/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/no-empty-object-type */
 /**
  * This file mirrors `crates/rust-analyzer/src/lsp_ext.rs` declarations.
  */
diff --git a/src/tools/rust-analyzer/editors/code/src/main.ts b/src/tools/rust-analyzer/editors/code/src/main.ts
index c84b69b66cd..451294e26f6 100644
--- a/src/tools/rust-analyzer/editors/code/src/main.ts
+++ b/src/tools/rust-analyzer/editors/code/src/main.ts
@@ -214,6 +214,7 @@ function checkConflictingExtensions() {
                     "both plugins to not work correctly. You should disable one of them.",
                 "Got it",
             )
+            // eslint-disable-next-line no-console
             .then(() => {}, console.error);
     }
 }
diff --git a/src/tools/rust-analyzer/editors/code/src/persistent_state.ts b/src/tools/rust-analyzer/editors/code/src/persistent_state.ts
index cebd16a3c90..3f90cd3bb93 100644
--- a/src/tools/rust-analyzer/editors/code/src/persistent_state.ts
+++ b/src/tools/rust-analyzer/editors/code/src/persistent_state.ts
@@ -14,6 +14,7 @@ export class PersistentState {
     get serverVersion(): string | undefined {
         return this.globalState.get("serverVersion");
     }
+
     async updateServerVersion(value: string | undefined) {
         await this.globalState.update("serverVersion", value);
     }
diff --git a/src/tools/rust-analyzer/editors/code/src/snippets.ts b/src/tools/rust-analyzer/editors/code/src/snippets.ts
index a469a9cd1f4..e3f43a80670 100644
--- a/src/tools/rust-analyzer/editors/code/src/snippets.ts
+++ b/src/tools/rust-analyzer/editors/code/src/snippets.ts
@@ -24,9 +24,7 @@ export async function applySnippetWorkspaceEdit(
                 for (const indel of edits) {
                     assert(
                         !(indel instanceof vscode.SnippetTextEdit),
-                        `bad ws edit: snippet received with multiple edits: ${JSON.stringify(
-                            edit,
-                        )}`,
+                        `bad ws edit: snippet received with multiple edits: ${JSON.stringify(edit)}`,
                     );
                     builder.replace(indel.range, indel.newText);
                 }
diff --git a/src/tools/rust-analyzer/editors/code/src/syntax_tree_provider.ts b/src/tools/rust-analyzer/editors/code/src/syntax_tree_provider.ts
index 3f7e30f13a3..b86f8cbc707 100644
--- a/src/tools/rust-analyzer/editors/code/src/syntax_tree_provider.ts
+++ b/src/tools/rust-analyzer/editors/code/src/syntax_tree_provider.ts
@@ -7,8 +7,10 @@ import * as ra from "./lsp_ext";
 export class SyntaxTreeProvider implements vscode.TreeDataProvider<SyntaxElement> {
     private _onDidChangeTreeData: vscode.EventEmitter<SyntaxElement | undefined | void> =
         new vscode.EventEmitter<SyntaxElement | undefined | void>();
+
     readonly onDidChangeTreeData: vscode.Event<SyntaxElement | undefined | void> =
         this._onDidChangeTreeData.event;
+
     ctx: CtxInit;
     root: SyntaxNode | undefined;
     hideWhitespace: boolean = false;
diff --git a/src/tools/rust-analyzer/editors/code/src/test_explorer.ts b/src/tools/rust-analyzer/editors/code/src/test_explorer.ts
index de41d2a57ec..e45f8282942 100644
--- a/src/tools/rust-analyzer/editors/code/src/test_explorer.ts
+++ b/src/tools/rust-analyzer/editors/code/src/test_explorer.ts
@@ -133,7 +133,7 @@ export const prepareTestExplorer = (
         }
         if (scope) {
             const recursivelyRemove = (tests: vscode.TestItemCollection) => {
-                for (const [_, test] of tests) {
+                for (const [, test] of tests) {
                     if (!testSet.has(test.id)) {
                         deleteTest(test, tests);
                     } else {
diff --git a/src/tools/rust-analyzer/editors/code/src/toolchain.ts b/src/tools/rust-analyzer/editors/code/src/toolchain.ts
index e8bab9c3d84..bb061442953 100644
--- a/src/tools/rust-analyzer/editors/code/src/toolchain.ts
+++ b/src/tools/rust-analyzer/editors/code/src/toolchain.ts
@@ -18,6 +18,22 @@ export interface ArtifactSpec {
     filter?: (artifacts: CompilationArtifact[]) => CompilationArtifact[];
 }
 
+interface CompilerMessage {
+    reason: string;
+    executable?: string;
+    target: {
+        crate_types: [string, ...string[]];
+        kind: [string, ...string[]];
+        name: string;
+    };
+    profile: {
+        test: boolean;
+    };
+    message: {
+        rendered: string;
+    };
+}
+
 export class Cargo {
     constructor(
         readonly rootFolder: string,
@@ -109,7 +125,7 @@ export class Cargo {
 
     private async runCargo(
         cargoArgs: string[],
-        onStdoutJson: (obj: any) => void,
+        onStdoutJson: (obj: CompilerMessage) => void,
         onStderrString: (data: string) => void,
         env?: Record<string, string>,
     ): Promise<number> {
@@ -131,7 +147,7 @@ export class Cargo {
                 onStdoutJson(message);
             });
 
-            cargo.on("exit", (exitCode, _) => {
+            cargo.on("exit", (exitCode) => {
                 if (exitCode === 0) resolve(exitCode);
                 else reject(new Error(`exit code: ${exitCode}.`));
             });
diff --git a/src/tools/rust-analyzer/editors/code/src/util.ts b/src/tools/rust-analyzer/editors/code/src/util.ts
index d7ca6b3557d..2f7702baebb 100644
--- a/src/tools/rust-analyzer/editors/code/src/util.ts
+++ b/src/tools/rust-analyzer/editors/code/src/util.ts
@@ -104,6 +104,7 @@ export function isDocumentInWorkspace(document: RustDocument): boolean {
 }
 
 /** Sets ['when'](https://code.visualstudio.com/docs/getstarted/keybindings#_when-clause-contexts) clause contexts */
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
 export function setContextValue(key: string, value: any): Thenable<void> {
     return vscode.commands.executeCommand("setContext", key, value);
 }
@@ -167,27 +168,35 @@ export class LazyOutputChannel implements vscode.OutputChannel {
     append(value: string): void {
         this.channel.append(value);
     }
+
     appendLine(value: string): void {
         this.channel.appendLine(value);
     }
+
     replace(value: string): void {
         this.channel.replace(value);
     }
+
     clear(): void {
         if (this._channel) {
             this._channel.clear();
         }
     }
-    show(preserveFocus?: boolean): void;
-    show(column?: vscode.ViewColumn, preserveFocus?: boolean): void;
-    show(column?: any, preserveFocus?: any): void {
-        this.channel.show(column, preserveFocus);
+
+    show(columnOrPreserveFocus?: vscode.ViewColumn | boolean, preserveFocus?: boolean): void {
+        if (typeof columnOrPreserveFocus === "boolean") {
+            this.channel.show(columnOrPreserveFocus);
+        } else {
+            this.channel.show(columnOrPreserveFocus, preserveFocus);
+        }
     }
+
     hide(): void {
         if (this._channel) {
             this._channel.hide();
         }
     }
+
     dispose(): void {
         if (this._channel) {
             this._channel.dispose();
@@ -276,6 +285,7 @@ export async function spawnAsync(
             stderr: res.stderr,
             status: res.status,
         };
+        // eslint-disable-next-line @typescript-eslint/no-explicit-any
     } catch (e: any) {
         return {
             stdout: e.stdout,
diff --git a/src/tools/rust-analyzer/editors/code/tests/unit/index.ts b/src/tools/rust-analyzer/editors/code/tests/unit/index.ts
index 8ad46546abd..bf74060c730 100644
--- a/src/tools/rust-analyzer/editors/code/tests/unit/index.ts
+++ b/src/tools/rust-analyzer/editors/code/tests/unit/index.ts
@@ -1,6 +1,7 @@
 import * as assert from "node:assert/strict";
 import { readdir } from "fs/promises";
 import * as path from "path";
+import { pathToFileURL } from "url";
 
 class Test {
     readonly name: string;
@@ -67,7 +68,7 @@ export async function run(): Promise<void> {
     );
     for (const testFile of testFiles) {
         try {
-            const testModule = require(path.resolve(__dirname, testFile));
+            const testModule = await import(pathToFileURL(path.resolve(__dirname, testFile)).href);
             await testModule.getTests(context);
         } catch (e) {
             error(`${e}`);
diff --git a/src/tools/rust-analyzer/editors/code/tests/unit/tasks.test.ts b/src/tools/rust-analyzer/editors/code/tests/unit/tasks.test.ts
index 9bccaaf3d47..9b5d98ee7e9 100644
--- a/src/tools/rust-analyzer/editors/code/tests/unit/tasks.test.ts
+++ b/src/tools/rust-analyzer/editors/code/tests/unit/tasks.test.ts
@@ -114,6 +114,7 @@ function f(task: vscode.Task): {
         execution,
     };
 }
+
 function executionToSimple(
     taskExecution: vscode.ProcessExecution | vscode.ShellExecution | vscode.CustomExecution,
 ): {
@@ -122,8 +123,8 @@ function executionToSimple(
     const exec = taskExecution as vscode.ProcessExecution | vscode.ShellExecution;
     if (exec instanceof vscode.ShellExecution) {
         return {
-            command: typeof exec.command === "string" ? exec.command : exec.command.value,
-            args: exec.args.map((arg) => {
+            command: typeof exec.command === "string" ? exec.command : (exec.command?.value ?? ""),
+            args: (exec.args ?? []).map((arg) => {
                 if (typeof arg === "string") {
                     return arg;
                 }
diff --git a/src/tools/rust-analyzer/editors/code/tsconfig.eslint.json b/src/tools/rust-analyzer/editors/code/tsconfig.eslint.json
index 5e2b33ca39f..eceffeef598 100644
--- a/src/tools/rust-analyzer/editors/code/tsconfig.eslint.json
+++ b/src/tools/rust-analyzer/editors/code/tsconfig.eslint.json
@@ -6,6 +6,6 @@
         "src",
         "tests",
         // these are the eslint-only inclusions
-        ".eslintrc.js"
+        "eslint.config.mts"
     ]
 }
diff --git a/src/tools/rust-analyzer/editors/code/tsconfig.json b/src/tools/rust-analyzer/editors/code/tsconfig.json
index 87cfd1b2ee1..a13afab1705 100644
--- a/src/tools/rust-analyzer/editors/code/tsconfig.json
+++ b/src/tools/rust-analyzer/editors/code/tsconfig.json
@@ -2,18 +2,17 @@
     "extends": "@tsconfig/strictest/tsconfig.json",
     "compilerOptions": {
         "esModuleInterop": false,
-        "module": "Node16",
-        "moduleResolution": "Node16",
-        "target": "ES2021",
+        "module": "NodeNext",
+        "moduleResolution": "nodenext",
+        "target": "ES2024",
         "outDir": "out",
-        "lib": ["ES2021"],
+        "lib": ["ES2024"],
         "sourceMap": true,
         "rootDir": ".",
         "newLine": "lf",
-
         // FIXME: https://github.com/rust-lang/rust-analyzer/issues/15253
         "exactOptionalPropertyTypes": false
     },
-    "exclude": ["node_modules", ".vscode-test"],
+    "exclude": ["node_modules", ".vscode-test", "out"],
     "include": ["src", "tests"]
 }
diff --git a/src/tools/rust-analyzer/rust-version b/src/tools/rust-analyzer/rust-version
index 6cd39fabeee..e24e08d0687 100644
--- a/src/tools/rust-analyzer/rust-version
+++ b/src/tools/rust-analyzer/rust-version
@@ -1 +1 @@
-e0be1a02626abef2878cb7f4aaef7ae409477112
+daf59857d6d2b87af4b846316bf1561a6083ed51
diff --git a/src/tools/rust-analyzer/xtask/src/dist.rs b/src/tools/rust-analyzer/xtask/src/dist.rs
index c6a0be8aeb9..99483f4a5dc 100644
--- a/src/tools/rust-analyzer/xtask/src/dist.rs
+++ b/src/tools/rust-analyzer/xtask/src/dist.rs
@@ -38,11 +38,11 @@ impl flags::Dist {
                 // A hack to make VS Code prefer nightly over stable.
                 format!("{VERSION_NIGHTLY}.{patch_version}")
             };
-            dist_server(sh, &format!("{version}-standalone"), &target, allocator)?;
+            dist_server(sh, &format!("{version}-standalone"), &target, allocator, self.zig)?;
             let release_tag = if stable { date_iso(sh)? } else { "nightly".to_owned() };
             dist_client(sh, &version, &release_tag, &target)?;
         } else {
-            dist_server(sh, "0.0.0-standalone", &target, allocator)?;
+            dist_server(sh, "0.0.0-standalone", &target, allocator, self.zig)?;
         }
         Ok(())
     }
@@ -83,6 +83,7 @@ fn dist_server(
     release: &str,
     target: &Target,
     allocator: Malloc,
+    zig: bool,
 ) -> anyhow::Result<()> {
     let _e = sh.push_env("CFG_RELEASE", release);
     let _e = sh.push_env("CARGO_PROFILE_RELEASE_LTO", "thin");
@@ -92,13 +93,14 @@ fn dist_server(
     //   * on Linux, this blows up the binary size from 8MB to 43MB, which is unreasonable.
     // let _e = sh.push_env("CARGO_PROFILE_RELEASE_DEBUG", "1");
 
-    if target.name.contains("-linux-") {
-        env::set_var("CC", "clang");
-    }
-
-    let target_name = &target.name;
+    let linux_target = target.is_linux();
+    let target_name = match &target.libc_suffix {
+        Some(libc_suffix) if zig => format!("{}.{libc_suffix}", target.name),
+        _ => target.name.to_owned(),
+    };
     let features = allocator.to_features();
-    cmd!(sh, "cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --target {target_name} {features...} --release").run()?;
+    let command = if linux_target && zig { "zigbuild" } else { "build" };
+    cmd!(sh, "cargo {command} --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --target {target_name} {features...} --release").run()?;
 
     let dst = Path::new("dist").join(&target.artifact_name);
     if target_name.contains("-windows-") {
@@ -156,6 +158,7 @@ fn zip(src_path: &Path, symbols_path: Option<&PathBuf>, dest_path: &Path) -> any
 
 struct Target {
     name: String,
+    libc_suffix: Option<String>,
     server_path: PathBuf,
     symbols_path: Option<PathBuf>,
     artifact_name: String,
@@ -177,6 +180,10 @@ impl Target {
                 }
             }
         };
+        let (name, libc_suffix) = match name.split_once('.') {
+            Some((l, r)) => (l.to_owned(), Some(r.to_owned())),
+            None => (name, None),
+        };
         let out_path = project_root.join("target").join(&name).join("release");
         let (exe_suffix, symbols_path) = if name.contains("-windows-") {
             (".exe".into(), Some(out_path.join("rust_analyzer.pdb")))
@@ -185,7 +192,11 @@ impl Target {
         };
         let server_path = out_path.join(format!("rust-analyzer{exe_suffix}"));
         let artifact_name = format!("rust-analyzer-{name}{exe_suffix}");
-        Self { name, server_path, symbols_path, artifact_name }
+        Self { name, libc_suffix, server_path, symbols_path, artifact_name }
+    }
+
+    fn is_linux(&self) -> bool {
+        self.name.contains("-linux-")
     }
 }
 
diff --git a/src/tools/rust-analyzer/xtask/src/flags.rs b/src/tools/rust-analyzer/xtask/src/flags.rs
index ebb9e71a4f4..d03e2f8437e 100644
--- a/src/tools/rust-analyzer/xtask/src/flags.rs
+++ b/src/tools/rust-analyzer/xtask/src/flags.rs
@@ -57,6 +57,8 @@ xflags::xflags! {
             /// Use jemalloc allocator for server
             optional --jemalloc
             optional --client-patch-version version: String
+            /// Use cargo-zigbuild
+            optional --zig
         }
         /// Read a changelog AsciiDoc file and update the GitHub Releases entry in Markdown.
         cmd publish-release-notes {
@@ -144,6 +146,7 @@ pub struct Dist {
     pub mimalloc: bool,
     pub jemalloc: bool,
     pub client_patch_version: Option<String>,
+    pub zig: bool,
 }
 
 #[derive(Debug)]
diff --git a/src/tools/rust-analyzer/xtask/src/release.rs b/src/tools/rust-analyzer/xtask/src/release.rs
index 8e56ce439c5..9f65c402953 100644
--- a/src/tools/rust-analyzer/xtask/src/release.rs
+++ b/src/tools/rust-analyzer/xtask/src/release.rs
@@ -50,7 +50,7 @@ impl flags::Release {
             .unwrap_or_default();
 
         let tags = cmd!(sh, "git tag --list").read()?;
-        let prev_tag = tags.lines().filter(|line| is_release_tag(line)).last().unwrap();
+        let prev_tag = tags.lines().filter(|line| is_release_tag(line)).next_back().unwrap();
 
         let contents = changelog::get_changelog(sh, changelog_n, &commit, prev_tag, &today)?;
         let path = changelog_dir.join(format!("{today}-changelog-{changelog_n}.adoc"));
diff --git a/src/tools/rustdoc/Cargo.toml b/src/tools/rustdoc/Cargo.toml
index c4101f72cc2..d1682758d36 100644
--- a/src/tools/rustdoc/Cargo.toml
+++ b/src/tools/rustdoc/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "rustdoc-tool"
 version = "0.0.0"
-edition = "2021"
+edition = "2024"
 
 # Cargo adds a number of paths to the dylib search path on windows, which results in
 # the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool"
diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs
index ea8ca38cb77..664c90b991a 100644
--- a/src/tools/rustfmt/src/macros.rs
+++ b/src/tools/rustfmt/src/macros.rs
@@ -12,7 +12,7 @@
 use std::collections::HashMap;
 use std::panic::{AssertUnwindSafe, catch_unwind};
 
-use rustc_ast::token::{BinOpToken, Delimiter, Token, TokenKind};
+use rustc_ast::token::{Delimiter, Token, TokenKind};
 use rustc_ast::tokenstream::{TokenStream, TokenStreamIter, TokenTree};
 use rustc_ast::{ast, ptr};
 use rustc_ast_pretty::pprust;
@@ -841,7 +841,7 @@ impl MacroArgParser {
             match tok {
                 TokenTree::Token(
                     Token {
-                        kind: TokenKind::BinOp(BinOpToken::Plus),
+                        kind: TokenKind::Plus,
                         ..
                     },
                     _,
@@ -855,7 +855,7 @@ impl MacroArgParser {
                 )
                 | TokenTree::Token(
                     Token {
-                        kind: TokenKind::BinOp(BinOpToken::Star),
+                        kind: TokenKind::Star,
                         ..
                     },
                     _,
@@ -1088,14 +1088,32 @@ fn force_space_before(tok: &TokenKind) -> bool {
         | TokenKind::Gt
         | TokenKind::AndAnd
         | TokenKind::OrOr
-        | TokenKind::Not
+        | TokenKind::Bang
         | TokenKind::Tilde
-        | TokenKind::BinOpEq(_)
+        | TokenKind::PlusEq
+        | TokenKind::MinusEq
+        | TokenKind::StarEq
+        | TokenKind::SlashEq
+        | TokenKind::PercentEq
+        | TokenKind::CaretEq
+        | TokenKind::AndEq
+        | TokenKind::OrEq
+        | TokenKind::ShlEq
+        | TokenKind::ShrEq
         | TokenKind::At
         | TokenKind::RArrow
         | TokenKind::LArrow
         | TokenKind::FatArrow
-        | TokenKind::BinOp(_)
+        | TokenKind::Plus
+        | TokenKind::Minus
+        | TokenKind::Star
+        | TokenKind::Slash
+        | TokenKind::Percent
+        | TokenKind::Caret
+        | TokenKind::And
+        | TokenKind::Or
+        | TokenKind::Shl
+        | TokenKind::Shr
         | TokenKind::Pound
         | TokenKind::Dollar => true,
         _ => false,
@@ -1113,8 +1131,8 @@ fn next_space(tok: &TokenKind) -> SpaceState {
     debug!("next_space: {:?}", tok);
 
     match tok {
-        TokenKind::Not
-        | TokenKind::BinOp(BinOpToken::And)
+        TokenKind::Bang
+        | TokenKind::And
         | TokenKind::Tilde
         | TokenKind::At
         | TokenKind::Comma
diff --git a/src/tools/rustfmt/src/spanned.rs b/src/tools/rustfmt/src/spanned.rs
index e93eb53cd87..507647566d4 100644
--- a/src/tools/rustfmt/src/spanned.rs
+++ b/src/tools/rustfmt/src/spanned.rs
@@ -58,6 +58,7 @@ implement_spanned!(ast::ExprField);
 implement_spanned!(ast::ForeignItem);
 implement_spanned!(ast::Item);
 implement_spanned!(ast::Local);
+implement_spanned!(ast::WherePredicate);
 
 impl Spanned for ast::Stmt {
     fn span(&self) -> Span {
@@ -149,12 +150,6 @@ impl Spanned for ast::FieldDef {
     }
 }
 
-impl Spanned for ast::WherePredicate {
-    fn span(&self) -> Span {
-        self.span
-    }
-}
-
 impl Spanned for ast::FnRetTy {
     fn span(&self) -> Span {
         match *self {
diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs
index 7b44b47c719..06a67334086 100644
--- a/src/tools/rustfmt/src/types.rs
+++ b/src/tools/rustfmt/src/types.rs
@@ -463,8 +463,9 @@ impl Rewrite for ast::WherePredicate {
     }
 
     fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
+        let attrs_str = self.attrs.rewrite_result(context, shape)?;
         // FIXME: dead spans?
-        let result = match self.kind {
+        let pred_str = &match self.kind {
             ast::WherePredicateKind::BoundPredicate(ast::WhereBoundPredicate {
                 ref bound_generic_params,
                 ref bounded_ty,
@@ -499,6 +500,38 @@ impl Rewrite for ast::WherePredicate {
             }
         };
 
+        let mut result = String::with_capacity(attrs_str.len() + pred_str.len() + 1);
+        result.push_str(&attrs_str);
+        let pred_start = self.span.lo();
+        let line_len = last_line_width(&attrs_str) + 1 + first_line_width(&pred_str);
+        if let Some(last_attr) = self.attrs.last().filter(|last_attr| {
+            contains_comment(context.snippet(mk_sp(last_attr.span.hi(), pred_start)))
+        }) {
+            result = combine_strs_with_missing_comments(
+                context,
+                &result,
+                &pred_str,
+                mk_sp(last_attr.span.hi(), pred_start),
+                Shape {
+                    width: shape.width.min(context.config.inline_attribute_width()),
+                    ..shape
+                },
+                !last_attr.is_doc_comment(),
+            )?;
+        } else {
+            if !self.attrs.is_empty() {
+                if context.config.inline_attribute_width() < line_len
+                    || self.attrs.len() > 1
+                    || self.attrs.last().is_some_and(|a| a.is_doc_comment())
+                {
+                    result.push_str(&shape.indent.to_string_with_newline(context.config));
+                } else {
+                    result.push(' ');
+                }
+            }
+            result.push_str(&pred_str);
+        }
+
         Ok(result)
     }
 }
diff --git a/src/tools/rustfmt/tests/target/cfg_attribute_in_where.rs b/src/tools/rustfmt/tests/target/cfg_attribute_in_where.rs
new file mode 100644
index 00000000000..11f495b1629
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/cfg_attribute_in_where.rs
@@ -0,0 +1,116 @@
+// rustfmt-inline_attribute_width: 40
+
+#![crate_type = "lib"]
+#![feature(cfg_attribute_in_where)]
+use std::marker::PhantomData;
+
+#[cfg(a)]
+trait TraitA {}
+
+#[cfg(b)]
+trait TraitB {}
+
+trait A<T>
+where
+    #[cfg = a_very_long_attribute_name]
+    T: TraitA,
+    #[cfg = another_very_long_attribute_name]
+    T: TraitB,
+{
+    type B<U>
+    where
+        #[cfg = a]
+        // line comment after the attribute
+        U: TraitA,
+        #[cfg = b]
+        /* block comment after the attribute */
+        U: TraitB,
+        #[cfg = a] // short
+        U: TraitA,
+        #[cfg = b] /* short */ U: TraitB;
+
+    fn foo<U>(&self)
+    where
+        /// line doc comment before the attribute
+        U: TraitA,
+        /** line doc block comment before the attribute */
+        U: TraitB;
+}
+
+impl<T> A<T> for T
+where
+    #[doc = "line doc before the attribute"]
+    T: TraitA,
+    /** short doc */
+    T: TraitB,
+{
+    type B<U>
+        = ()
+    where
+        #[doc = "short"] U: TraitA,
+        #[doc = "short"]
+        #[cfg = a]
+        U: TraitB;
+
+    fn foo<U>(&self)
+    where
+        #[cfg = a]
+        #[cfg = b]
+        U: TraitA,
+        /// line doc
+        #[cfg = c]
+        U: TraitB,
+    {
+    }
+}
+
+struct C<T>
+where
+    #[cfg = a] T: TraitA,
+    #[cfg = b] T: TraitB,
+{
+    _t: PhantomData<T>,
+}
+
+union D<T>
+where
+    #[cfg = a] T: TraitA,
+    #[cfg = b] T: TraitB,
+{
+    _t: PhantomData<T>,
+}
+
+enum E<T>
+where
+    #[cfg = a] T: TraitA,
+    #[cfg = b] T: TraitB,
+{
+    E(PhantomData<T>),
+}
+
+#[allow(type_alias_bounds)]
+type F<T>
+where
+    #[cfg = a] T: TraitA,
+    #[cfg = b] T: TraitB,
+= T;
+
+impl<T> C<T>
+where
+    #[cfg = a] T: TraitA,
+    #[cfg = b] T: TraitB,
+{
+    fn new<U>()
+    where
+        #[cfg = a] U: TraitA,
+        #[cfg = b] U: TraitB,
+    {
+    }
+}
+
+fn foo<T>()
+where
+    #[cfg = a] T: TraitA,
+    #[cfg = b] T: TraitB,
+{
+}
diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/src/tools/tidy/src/allowed_run_make_makefiles.txt
+++ /dev/null
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index 1e7eb82b83e..9f6d563166e 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -79,7 +79,6 @@ pub(crate) mod iter_header;
 pub mod known_bug;
 pub mod mir_opt_tests;
 pub mod pal;
-pub mod run_make_tests;
 pub mod rustdoc_css_themes;
 pub mod rustdoc_gui_tests;
 pub mod rustdoc_templates;
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index 13a558fea48..1d8514ef4c9 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -103,8 +103,6 @@ fn main() {
         check!(tests_revision_unpaired_stdout_stderr, &tests_path);
         check!(debug_artifacts, &tests_path);
         check!(ui_tests, &root_path, bless);
-        // FIXME(jieyouxu): remove this check once all run-make tests are ported over to rmake.rs.
-        check!(run_make_tests, &tests_path, &src_path, bless);
         check!(mir_opt_tests, &tests_path, bless);
         check!(rustdoc_gui_tests, &tests_path);
         check!(rustdoc_css_themes, &librustdoc_path);
diff --git a/src/tools/tidy/src/run_make_tests.rs b/src/tools/tidy/src/run_make_tests.rs
deleted file mode 100644
index 8d176787837..00000000000
--- a/src/tools/tidy/src/run_make_tests.rs
+++ /dev/null
@@ -1,104 +0,0 @@
-//! Tidy check to ensure that no new Makefiles are added under `tests/run-make/`.
-
-use std::collections::BTreeSet;
-use std::fs::File;
-use std::io::Write;
-use std::path::{Path, PathBuf};
-
-pub fn check(tests_path: &Path, src_path: &Path, bless: bool, bad: &mut bool) {
-    let mut is_sorted = true;
-
-    let allowed_makefiles = {
-        let mut total_lines = 0;
-        let mut prev_line = "";
-        let allowed_makefiles: BTreeSet<&str> = include_str!("allowed_run_make_makefiles.txt")
-            .lines()
-            .map(|line| {
-                total_lines += 1;
-
-                if prev_line > line {
-                    is_sorted = false;
-                }
-
-                prev_line = line;
-
-                line
-            })
-            .collect();
-
-        if !is_sorted && !bless {
-            tidy_error!(
-                bad,
-                "`src/tools/tidy/src/allowed_run_make_makefiles.txt` is not in order, likely \
-                because you modified it manually, please only update it with command \
-                `x test tidy --bless`"
-            );
-        }
-        if allowed_makefiles.len() != total_lines {
-            tidy_error!(
-                bad,
-                "`src/tools/tidy/src/allowed_run_make_makefiles.txt` contains duplicate entries, \
-                likely because you modified it manually, please only update it with command \
-                `x test tidy --bless`"
-            );
-        }
-
-        allowed_makefiles
-    };
-
-    let mut remaining_makefiles = allowed_makefiles.clone();
-
-    crate::walk::walk_no_read(
-        &[tests_path.join("run-make").as_ref()],
-        |_, _| false,
-        &mut |entry| {
-            if entry.file_type().map_or(true, |t| t.is_dir()) {
-                return;
-            }
-
-            if entry.file_name().to_str().map_or(true, |f| f != "Makefile") {
-                return;
-            }
-
-            let makefile_path = entry.path().strip_prefix(&tests_path).unwrap();
-            let makefile_path = makefile_path.to_str().unwrap().replace('\\', "/");
-
-            if !remaining_makefiles.remove(makefile_path.as_str()) {
-                tidy_error!(
-                    bad,
-                    "found run-make Makefile not permitted in \
-                `src/tools/tidy/src/allowed_run_make_makefiles.txt`, please write new run-make \
-                tests with `rmake.rs` instead: {}",
-                    entry.path().display()
-                );
-            }
-        },
-    );
-
-    // If there are any expected Makefiles remaining, they were moved or deleted.
-    // Our data must remain up to date, so they must be removed from
-    // `src/tools/tidy/src/allowed_run_make_makefiles.txt`.
-    // This can be done automatically on --bless, or else a tidy error will be issued.
-    if bless && (!remaining_makefiles.is_empty() || !is_sorted) {
-        let tidy_src = src_path.join("tools").join("tidy").join("src");
-        let org_file_path = tidy_src.join("allowed_run_make_makefiles.txt");
-        let temp_file_path = tidy_src.join("blessed_allowed_run_make_makefiles.txt");
-        let mut temp_file = t!(File::create_new(&temp_file_path));
-        for file in allowed_makefiles.difference(&remaining_makefiles) {
-            t!(writeln!(temp_file, "{file}"));
-        }
-        t!(std::fs::rename(&temp_file_path, &org_file_path));
-    } else {
-        for file in remaining_makefiles {
-            let mut p = PathBuf::from(tests_path);
-            p.push(file);
-            tidy_error!(
-                bad,
-                "Makefile `{}` no longer exists and should be removed from the exclusions in \
-                `src/tools/tidy/src/allowed_run_make_makefiles.txt`, you can run `x test tidy --bless` to update \
-                the allow list",
-                p.display()
-            );
-        }
-    }
-}
diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs
index 21b513629ed..205d6720718 100644
--- a/src/tools/tidy/src/style.rs
+++ b/src/tools/tidy/src/style.rs
@@ -72,12 +72,14 @@ const ANNOTATIONS_TO_IGNORE: &[&str] = &[
     "//@ normalize-stderr",
 ];
 
+const LINELENGTH_CHECK: &str = "linelength";
+
 // If you edit this, also edit where it gets used in `check` (calling `contains_ignore_directives`)
 const CONFIGURABLE_CHECKS: [&str; 11] = [
     "cr",
     "undocumented-unsafe",
     "tab",
-    "linelength",
+    LINELENGTH_CHECK,
     "filelength",
     "end-whitespace",
     "trailing-newlines",
@@ -250,14 +252,24 @@ enum Directive {
 // Use a fixed size array in the return type to catch mistakes with changing `CONFIGURABLE_CHECKS`
 // without changing the code in `check` easier.
 fn contains_ignore_directives<const N: usize>(
+    path_str: &str,
     can_contain: bool,
     contents: &str,
     checks: [&str; N],
 ) -> [Directive; N] {
-    if !can_contain {
+    // The rustdoc-json test syntax often requires very long lines, so the checks
+    // for long lines aren't really useful.
+    let always_ignore_linelength = path_str.contains("rustdoc-json");
+
+    if !can_contain && !always_ignore_linelength {
         return [Directive::Deny; N];
     }
+
     checks.map(|check| {
+        if check == LINELENGTH_CHECK && always_ignore_linelength {
+            return Directive::Ignore(false);
+        }
+
         // Update `can_contain` when changing this
         if contents.contains(&format!("// ignore-tidy-{check}"))
             || contents.contains(&format!("# ignore-tidy-{check}"))
@@ -367,6 +379,7 @@ pub fn check(path: &Path, bad: &mut bool) {
 
     walk(path, skip, &mut |entry, contents| {
         let file = entry.path();
+        let path_str = file.to_string_lossy();
         let filename = file.file_name().unwrap().to_string_lossy();
 
         let is_css_file = filename.ends_with(".css");
@@ -422,7 +435,7 @@ pub fn check(path: &Path, bad: &mut bool) {
             mut skip_copyright,
             mut skip_dbg,
             mut skip_odd_backticks,
-        ] = contains_ignore_directives(can_contain, &contents, CONFIGURABLE_CHECKS);
+        ] = contains_ignore_directives(&path_str, can_contain, &contents, CONFIGURABLE_CHECKS);
         let mut leading_new_lines = false;
         let mut trailing_new_lines = 0;
         let mut lines = 0;
@@ -502,7 +515,7 @@ pub fn check(path: &Path, bad: &mut bool) {
                 let contains_potential_directive =
                     possible_line_start && (line.contains("-tidy") || line.contains("tidy-"));
                 let has_recognized_ignore_directive =
-                    contains_ignore_directives(can_contain, line, CONFIGURABLE_CHECKS)
+                    contains_ignore_directives(&path_str, can_contain, line, CONFIGURABLE_CHECKS)
                         .into_iter()
                         .any(|directive| matches!(directive, Directive::Ignore(_)));
                 let has_alphabetical_directive = line.contains("tidy-alphabetical-start")